JavaScript: how to get private, privileged, public and static members (properties and methods)
After reading JavaScript inheritance – how and why and Explaining JavaScript scope and closures, I thought we’d combine the knowledge gained to talk about private, privileged, public and static members (properties and methods) for objects in JavaScript.
Background
For the developers coming from a heavy object-oriented background, defining and using these sort of members is key to all code being written. Not really so when you work with JavaScript, but I thought I’d explain how to use that sort of approach with JavaScript to make your code more versatile.
Putting together our object
We will put together a constructor object, of which you can create new instances by using the new keyword. Let’s start with an empty one, to get a hang of it:
// Constructor
function Kid (name) {
// Empty, for now
}
Now you can create as many kid objects you want, in this fashion:
var kenny = new Kid("Kenny");
Adding a private property
As we learned in the JavaScript scope and closures article, by declaring a variable within a function, it is only available from within there. So, if we want a private property of the Kid object, we do it like this:
// Constructor
function Kid (name) {
// Private
var idol = "Paris Hilton";
}
The idol property will only be available for the code inside the Kid function/object.
Adding a privileged method
A privileged method is a method having access to private properties, but at the same time publicly exposing itself (in JavaScript, also due to JavaScript scope and closures). You can delete or replace a privileged method, but you cannot alter its contents. I.e. this privileged method returns the value of a private property:
// Constructor
function Kid (name) {
// Private
var idol = "Paris Hilton";
// Privileged
this.getIdol = function () {
return idol;
};
}
Adding a public property and a public method
Now that we have private and privileged members out of the way, let’s look at the very basic nature of public properties and methods:
// Constructor
function Kid (name) {
// Public
this.name = name;
this.getName = function () {
return this.name;
};
}
The property name is publicly available for any call, just like the getName method is.
Update
Just as mentioned in the comments below, this way was only chosen and shown for clarity in comparison to the other types. The recommended way for public methods is using the prototype approach, and I’ve updated the code below to reflect that. E.g:
// Constructor
function Kid (name) {
// Public
this.name = name;
}
Kid.prototype.getName = function () {
return this.name;
};
Read more about it in JavaScript inheritance – how and why.
Adding a static property
A static member is shared by all instances of the class as well as the class itself (i.e. the Kid object), but it is only stored in one place. This means that its value is not inherited down to the object’s instances:
// Constructor
function Kid (name) {
// Constructor code
}
// Static property
Kid.town = "South Park";
Our complete object
Let’s take a look at our complete object, before we try accessing its properties and methods:
// Constructor
function Kid (name) {
// Private
var idol = "Paris Hilton";
// Privileged
this.getIdol = function () {
return idol;
};
// Public
this.name = name;
}
// Public
Kid.prototype.getName = function () {
return this.name;
};
// Static property
Kid.town = "South Park";
Creating an instance and checking access
Now, finally, it’s time to test how these different approaches work in practice. We start by creating an instance of the Kid object, and then test what different values we get back. The tests and their results are:
// Create a new instance
var cartman = new Kid("Cartman");
// Access private property
cartman.idol; // undefined
// Access privileged method
cartman.getIdol(); // "Paris Hilton"
// Access public property
cartman.name; // "Cartman"
// Access public method
cartman.getName(); // "Cartman"
// Access static property on an instance
cartman.town; // undefined
// Access static property on the constructor object
Kid.town; // "South Park"
Conclusion
I hope this has been a good way to pique your curiosity about your different options when it comes to objects and its members! Also, for those new to JavaScript, but experienced in object-oriented programming with other languages, hopefully this answered some of the questions you might have had.
Now go create objects!
27 Comments/Reactions
October 14th, 2008 at 13:49
Robert, use the constructor as global scope to define public methods could be a bad practice if not necessary since for every instance you could create N functions … The prototype chain is still the best way, or at least a closure for those public methods that do not require access to private constructor scope:
(function(){
function getName(){return this.name};
Kid = function(name){
this.name = name;
this.getName = getName;
};
})();
above example still emulate prototype behaviour so it does not make sense for me
October 14th, 2008 at 19:24
Andrea,
Oh, absolutely, the prototype way is the optimal and recommended path to take, and I went more into explaining it and why in my JavaScript inheritance article mentioned in the post.
The idea here was just to have it in the constructor so it would be easier to compare to the other types, and to have it all in one place, but if you were to create many instances of the same object, I’d refrain from the above approach for public methods.
October 14th, 2008 at 19:42
Nice and concise article.
One question about public methods, when I started with javascript about 10 years ago it was the “recommended” way to add a public method (or any method for that matter, no-one seemed to know how to make “hidden” methods) was using the
prototype-attribute of our objects. Like:Kid.prototype.getName = function () {
return this.name;
};
Doing so would, supposedly, reuse the method’s code if you have several objects. The way you showed in your example creates a public but “personal” method for each object, without reuse. I’ve seen this in many prominent javascripters examples. To me it seem like a waste. Is there any pros or cons, and what are they?
Are there more interesting articles comming, like a series?
TC&GB!
October 14th, 2008 at 19:56
Andreas,
Thank you!
And you’re absolutely right, and it’s what Andrea pointed out as well. My public method code here was more for clarity than best practice, so I’ve updated the article with a correction about using
prototype.Glad that you like the JavaScript articles! With the inheritance and the scope and closures articles, together with this one, I think there won’t be too many in the near future, but one never knows.
It all comes down to inspiration and what lines of thoughts I meet daily.
October 14th, 2008 at 21:26
Another in a fantastic line of JavaScript articles!
I have a question: is there a way of having private members that are accesible by public functions created as a prototype? In C++, which is the language I learned Object Orientation in, anything that didn’t need to be public was private. In JavaScript, if you use the prototype avenue, you’re forced to make members public to allow for them to be accessed by public methods.
Let’s say we have the following code:
function YourConstructor() {
var blah = 0;
}
and the following method:
YourConstructor.prototype.getSomething = function () {
return blah;
}
Obviously, instantiating the class as an object and then calling
getSomething()isn’t going to work. Because of this, I find myself making members public that don’t need to be, and that doesn’t make a ton of sense from the perspective of OOP. Obviously we have the advantage of a dynamic scope via thethiskeyword, but other than that, Class methods are really no more effective than regular functions that simply sift through public object members. Am I doing something wrong?October 14th, 2008 at 22:58
Andrew,
Thank you!
It’s a very good question, and something I’ve pondered too. Most of the time, I don’t even use prototypical inheritance, but instead work with the Yahoo JavaScript Module Pattern and good namespacing.
But, while typing this at least, if you go the prototype route (which you should, if you need proper inheritance), you need to use privileged or public methods in the constructor to achieve this.
October 15th, 2008 at 12:30
I wrote a couple of articles about all these questions, with solutions for emulated protected methods and problem explanation for shared in scope private variables (already linked in another Robert post)
Anyway, as Robert said, for the private variable usable via instance we need privileged methods, specially since Mozilla removed the second argument from eval function
Finally, with a dedicated closure it is possible to define prototypes that use private methods, always in that scope, so privileged method are usually not necessary at all
function Person(name){
this.name = name;
};
(function(){
// shared private method
function _getName(){
return "My name is " + this.name;
};
Person.prototype.getName = function(){
return _getName.call(this);
};
})();
Of course the constructor could be inside the closure as well, something like:
Person = (function(){ // closure for everything
function Person(){};
Person.prototype.dostuff = function(){ ... };
return Person;
})();
just to preserve the Function.prototype.name behaviour, where in Person case will be “Person” instead of an empty string
October 15th, 2008 at 13:14
Andrea,
Thank you! It passed my mind while writing to Andrew, but naturally, a closure with the constructor (and returning the constructor as well) together with private members is a possible approach.
The only downside, structure-wise, from that is that you can’t define anything private in the actual constructor, and access from somewhere else.
October 15th, 2008 at 13:38
True Robert, that approach is for private methods, not for private variables.
We could have private variables outside the constructor as well, but those will be shared from every instance, so will be more like private static variables
October 15th, 2008 at 14:07
Andrea,
Yeah, exactly my thinking.
October 15th, 2008 at 18:23
Hi there, I actually just sent you an email Robert.
With regards to using private methods and variable on the prototype, I believe you can do the following:
var MyClass = function() {
}
MyClass.prototype = new (function(){
this.myPublicMember = "public";
var myPrivateMember = "private";
});
I would love to see a post on using the prototype in much more detail.
Thanks
October 15th, 2008 at 19:05
Adam,
Interesting thinking!
The problem, however, with that approach is that you can’t access that private variable in any other method for the object. I.e., this won’t work:
MyClass.prototype.getPrivate = function(){
return myPrivateMember;
};
With Andrea’s solution above, it is possible with private variables accessible to all methods, as long as they’re declared within the closure, but outside the constructor.
Maybe I should write a post explaining what Andrea touched on above, with private members, to have it more easy to overview than in the comments.
October 15th, 2008 at 19:21
Hi Robert
Can you not do the following:
var MyClass = function() {
}
MyClass.prototype = new(function(){
var privateVar = 1;
function getPrivate() {
return privateVar;
}
this.getPrivate = getPrivate;
});
var myInstance = new MyClass();
alert(myInstance.getPrivate()); // this alerts 1
I just tested and it seemed to work.
October 15th, 2008 at 19:32
Adam,
Ah, I see what you mean. That does indeed work.
The problem with it, however, is that the prototype for MyClass becomes an anonymously created object, where you declare the public method
getPrivateinline in the constructor, instead of using a prototype.I.e. each instance would have to create its own
getPrivatemethod, instead of using the one inherited down through the prototype chain.October 15th, 2008 at 19:36
Ah ha! I see! You need to do a blog post on all this stuff, because I need to be writing my classes with the prototype much more often
October 15th, 2008 at 19:37
Adam,
I think I will write one, in some form at least.
October 16th, 2008 at 18:35
Guys, again do not make confusion, private variables are always shared by instances since these are in the prototype, whatever scope it has. I wrote these details in my document, Robert if you do not mind I would like to post it again: http://www.3site.eu/doc/
Kind Regards
October 16th, 2008 at 19:42
Andrea,
Well, they’re shared by instances, so-to-say, but not by prototype methods, and that’s what Adam was aiming for.
Also, good posting the link, it’s good to have in this context!
October 17th, 2008 at 10:08
Very simple and really helpfull post. I’m waiting another one related with this topic.
Thanks!!
October 17th, 2008 at 10:50
Bleyder,
Glad that you liked it!
October 21st, 2008 at 23:08
[...] for more information about inheritance – intrigued by the concept myself, and also inspired by Andrea Giammarchi’s comment , I though I’d come up with some scary [...]
December 22nd, 2008 at 11:53
Basic question really:
I can’t see any difference in the syntax for a privileged method and a public method (when not using prototype) so… is a method called public/privileged based on the variables it access?
Thanks in advance
JT.
December 22nd, 2008 at 20:46
John,
Yeah, basically. A privileged method can access private members, whereas, in more regular languages, public methods can’t really do that.
August 21st, 2009 at 9:35
Hi Robert:
I am new at Javascript (but learning hard). Your articles are really nice.
Regarding the solution posted above by Adam Silver, I cannot see anything wrong with it; he is creating MyClass prototype from another (anonymous) object (thus making a copy the getPrivate() function). Once he has fed MyClass prototype, I cannot see why each MyClass instance needs its own copy of getPrivate(). On the contrary, I think all instances share the same getPrivate() function; in fact, MyClass constructor is an empty function, so there is no chance to redefine a new getPrivate() function each time you create a new MyClass instance.
It is true that all instances share the same privateVar as well, but this is something (as you have posted elsewhere) that cannot be resolved by the language (outside the constructor, I mean).
So, from my point of view, Adam’s approach is fully correct.
If I am wrong, explain it to me please (with some illustrative examples if you are so kind).
Thank you in advance.
December 9th, 2009 at 0:36
David Serrano,
Sorry for a late reply!
And thanks, I’m glad that you like my articles on JavaScript!
Adam’s example does indeed work and allows the desired access. The downside of it, though, is that it will affect performance. For any method of an object that you will create several instances of, you would want to have those methods on the prototype instead.
March 12th, 2010 at 21:28
I don’t believe static members can be emulated.
Kid.town = "South Park";does not make town a member of any Kid object (created with operator new). You have to go further and also write
Kid.prototype.town = "South Park";This may be as close as you can get, but Kid.town still doesn’t emulate a static variable since the individual values of town can be changed at will without effecting the others. The best you can do is to give the Kid class and all Kid objects identical copies and hope no one makes any changes.
March 13th, 2010 at 23:37
Mark,
I understand what you are saying, This was mainly meant as an introduction/execrcise for people coming from other languages, although in reality there’s no exact mapping.
Write a comment
Twitter reactions