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! π
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:
<code>
(function(){
function getName(){return this.name};
Kid = function(name){
this.name = name;
this.getName = getName;
};
})();
</code>
above example still emulate prototype behaviour so it does not make sense for me π
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.
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 <code>prototype</code>-attribute of our objects. Like:
<code>
Kid.prototype.getName = function () {
return this.name;
};
</code>
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!
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 <code>prototype</code>.
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.
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.
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:
<code>
function YourConstructor() {
var blah = 0;
}
</code>
and the following method:
<code>
YourConstructor.prototype.getSomething = function () {
return blah;
}
</code>
Obviously, instantiating the class as an object and then calling <code>getSomething()</code> 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 the <code>this</code> keyword, 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?
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 π
<code>
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);
};
})();
</code>
Of course the constructor could be inside the closure as well, something like:
<code>
Person = (function(){ // closure for everything
function Person(){};
Person.prototype.dostuff = function(){ … };
return Person;
})();
</code>
just to preserve the Function.prototype.name behaviour, where in Person case will be "Person" instead of an empty string
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.
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 π
Andrea,
Yeah, exactly my thinking. π
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:
<code>
var MyClass = function() {
}
MyClass.prototype = new (function(){
this.myPublicMember = "public";
var myPrivateMember = "private";
});
</code>
I would love to see a post on using the prototype in much more detail.
Thanks
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:
<code>
MyClass.prototype.getPrivate = function(){
return myPrivateMember;
};</code>
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.
Hi Robert
Can you not do the following:
<code>
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
</code>
I just tested and it seemed to work.
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 <code>getPrivate</code> inline in the constructor, instead of using a prototype.
I.e. each instance would have to create its own <code>getPrivate</code> method, instead of using the one inherited down through the prototype chain.
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 π
Adam,
I think I will write one, in some form at least. π
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 π
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!
Very simple and really helpfull post. I'm waiting another one related with this topic.
Thanks!!
Bleyder,
Glad that you liked it! π
[…] 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 […]
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.
John,
Yeah, basically. A privileged method can access private members, whereas, in more regular languages, public methods can’t really do that.
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.
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.
I don't believe static members can be emulated.
<code>Kid.town = "South Park";</code>
does not make town a member of any Kid object (created with operator new). You have to go further and also write
<code>Kid.prototype.town = "South Park";</code>
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.
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.
Hello Robert,
So do you recommend using the module pattern from Y! or the .prototype inheritance?
Ionut,
It totally depends on your situation. But overall, don't overuse inheritance unless there's an actual need for it.
As i see it the module/revealing module pattern is suitable for singleton situations, like let's say a single main slider on a page. For multiple instances you have to build a special pattern made with prototypical inheritance. Am i right?
Ionut,
It is originally meant for singletons, but can easily be extended to act as a constructor. Please see Douglas Crockford’s presentation, especially page 66, for more info.
I have different technique of creating private attributes as I need my ordinary public prototypical API functions to be able to modify the private attributes.
The idea is by creating private attributes holder identified by random string. The random string should be hard enough to be guessed by outside world.
I wrote an article about that here: http://www.kodejavascript.com/?qp=node/29.
Aldian,
Sure, that's another approach to it.
Can an object instance refer to the static properties without using the class name? Such as in PHP, self::$staticClassProperty?
ItsLeeOwen,
Depends on context – generally you need to know the name, since there aren’t really static members in that sense in JavaScript.
[…] Private, Privileged, Public And Static Members […]
Hi nice article, please find related article here http://www.vishalpatwardhan.com/2012/11/creating-classes-in-javascript.html
Hey thanks a lot for sharing such a wonderful article about javascript.
Thanks
Dhanesh Mane
Hello, Robert,
First, really good article, many things are clearer to me second, as you mentioned object instances doesn’t inherit values from static members, should I attach those values to Object.prototype?
With greetings,
Alan
Attaching things to Object prototype is very risky, and will affect all objects. I’d rather recommend using it in the single specific use cases.
Thanks a lot!You saved me from completing a course!
Ha ha! Well, completing the course is probably good anyway, but glad this was useful for you!