JavaScript: how to get private, privileged, public and static members (properties and methods)

Published on Tuesday, October 14th, 2008

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! :-)

21 comments

  • Andrea Giammarchi
    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 :)

  • Robert Nyman - author
    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.

  • Andreas Rydberg
    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!

  • Robert Nyman - author
    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.

  • Andrew Noyes
    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 the this 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?

  • Robert Nyman - author
    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.

  • Andrea Giammarchi
    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 :P

    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

  • Robert Nyman - author
    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.

  • Andrea Giammarchi
    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 :)

  • Robert Nyman - author
    October 15th, 2008 at 14:07

    Andrea,

    Yeah, exactly my thinking. :-)

  • Adam Silver
    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

  • Robert Nyman - author
    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.

  • Adam Silver
    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.

  • Robert Nyman - author
    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 getPrivate inline in the constructor, instead of using a prototype.

    I.e. each instance would have to create its own getPrivate method, instead of using the one inherited down through the prototype chain.

  • Adam Silver
    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 :)

  • Robert Nyman - author
    October 15th, 2008 at 19:37

    Adam,

    I think I will write one, in some form at least. :-)

  • Andrea Giammarchi
    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 :)

  • Robert Nyman - author
    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!

  • Bleyder
    October 17th, 2008 at 10:08

    Very simple and really helpfull post. I’m waiting another one related with this topic.

    Thanks!!

  • Robert Nyman - author
    October 17th, 2008 at 10:50

    Bleyder,

    Glad that you liked it! :-)

  • JavaScript inheritance - experimenting with syntax alternatives and private variables - Robert’s talk - Web development and Internet trends
    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 [...]

Share your thoughts:

HTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> . If you want to display code examples, please remember to write &lt; for < and &gt; for >.

Comment preview

Top results