JavaScript inheritance – experimenting with syntax alternatives and private variables

After my recent posts about JavaScript, there were some people asking 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 shit. πŸ™‚

Prerequisites

Before reading this article, I strongly recommend reading JavaScript inheritance – how and why and Explaining JavaScript scope and closures first, since many phenomenon below will have their explanation there.

Article objective

After this article, there will be no holy grail of how to code inheritance in JavaScript. I will introduce some common ways, touch on their problems and what one might want to achieve. Most of all, it’s a lesson in very different syntaxes for doing the same thing, and opening your to the wonderful and magical JavaScript world. πŸ™‚

At the end of the day, though, it’s up to you to choose what you seem best, or just be inspired by the many options you have to code JavaScript.

First inheritance steps

Let’s start with our first inheritance example, look at the code, an then see what’s good respectively not so good with it.

Inheritance from a regular object

I thought we’d start out easy, with inheriting from a regular object:

// Basic object
var Base = {
	
	// Public properties and methods
	dayName : "Tuesday",
	
	day : this.dayName,
	
	getDay : function () {
		return this.dayName;
	},
	
	setDay : function (newDayName) {
		this.dayName = newDayName;
	}
};

Cool so far? Good. Let’s create an object which inherits from our basic Base object:

// Using new Base() is not an option, 
// since it isn't a constructor
Sub.prototype = Base;
function Sub () {
	// Constructor
};

A test run

var a = new Sub();
// Returns "Tuesday"
alert(a.getDay());

var b = new Sub();
// Returns "Tuesday"
alert(b.getDay());

// Sets dayName to "Wednesday"
a.setDay("Wednesday");

// Returns "Wednesday"
alert(a.getDay());

// Returns "Tuesday"
alert(b.getDay());

// Returns undefined
alert(b.day);

Everything above is probably what you expected, except the last one that returned undefined. The problem is that the Base object tries to set a property while it’s executing, and then it doesn’t have any internal reference. Using a method instead for the day property would be a possibility to make it work:

day : function () {
	return this.dayName;
}

What’s good

As mentioned in the comment, you can point out Base object as the ancestor to inherit its prototype from, but since Base isn’t a real constructor, you cannot call it with the new keyword. Basically, this means that the Base constructor isn’t run, until an instance of the Sub object is being created.

This can be a good thing, since you might not want any unnecessary code to be run in the constructor, before it’s actually time. Personally, I never have anything important in the constructor, but put in an init method instead, so I can completely control when it is being invoked.

Not so good

What’s less good here is that all properties and methods are declared inline of the Base object, meaning you can’t utilize the prototype behavior. Also, there’s no way to have any private variables.

Private variables/members and prototype

Something a lot of people ask about is if it’s possible to have private variables in an object, and then being able to access them through any prototype method. The answer is, unfortunately, no (kind of). For private methods, however, there is an opportunity which I will go into later below.

Starting the syntax circus

From here on, I will present three different syntax alternatives to basically achieve the same results, but in very different fashions. It will also show the problems with private variables and prototype, and how it does work with private methods.

Basic Prototype inheritance

First out is regular prototype inheritance, where one private variable and one private method are declared:

// Basic Prototype inheritance
function Base () {

	// Private variable
	var dayName = "Tuesday";
	
	// Private method
	function getPrivateDayName () {
		return dayName;
	}

	// Public properties and methods
	this.day = dayName;

	this.getDay = function () {
		return getPrivateDayName();
	};

	this.setDay = function (newDayName) {
		dayName = newDayName;
	};
};


Sub.prototype = new Base;
function Sub () {
	// Constructor
};

What’s good

Simple syntax and everything reachable from within the constructor.

Not so good

To be able to access the private variable and private method, everything needs to be within the constructor, instead of through prototype assignment. Not a recommendable approach.

Yahoo JavaScript Module Pattern

I’ve mentioned it before, but my personal favorite when it comes to singleton objects is the Yahoo JavaScript Module Pattern. With the prospect of prototype inheritance, you can also use it as the prototype ancestor object for any sub object you are interested in creating. Basically, like this:

// Yahoo JavaScript Module Pattern
var Base = function () {
	
	// Private variable
	var dayName = "Tuesday";
	
	// Private method
	var getPrivateDayName = function () {
		return dayName;
	}
	
	// Public properties and methods
	return {
		
		day : dayName,
		
		getDay : function () {
			return getPrivateDayName.call(this);
		},
		
		setDay : function (newDayName) {
			dayName = newDayName;
		}
	};
}();

// Using new Base() is not an option, 
// since it isn't a constructor
Sub.prototype = Base;
function Sub () {
	// Constructor
};

What’s good

Nice code structure, good separation between private and public properties and methods.

Not so good

It isn’t a “true” constructor, so you can’t call it with new. Also, all public properties and methods are inline in the object, so it can’t utilize the recommended prototype approach.

Closure-created constructor

This piece of code creates a closure where you have the constructor, private variables and methods and assigns prototype properties and methods to the object. It then return the actual constructor object, so the next time it is run it’s behaving just like a normal constructor, while the closure makes sure all methods and values are still accessible.

By far the coolest code, if you ask me. πŸ™‚

// Closure-created constructor
var Base = (function () {
	
	// Constructor
	function Base () {
		
	}
	
	// Private variable
	var dayName = "Tuesday";
	
	// Private method
	function getPrivateDayName () {
		return dayName;
	}
	
	// Public properties and methods
	Base.prototype.day = dayName;
	Base.prototype.getDay = function () {
		return getPrivateDayName.call(this);
	};
	
	Base.prototype.setDay = function (newDayName) {
		dayName = newDayName;
	};
	
	return Base;
})();


Sub.prototype = new Base;
function Sub () {
	// Constructor
};

What’s good

This code uses a closure to have a constructor initiated, with complete control over prototype properties and methods, which in turn have access to private variables and methods. Its structure, if you ask me, is very nice, because you have the constructor and the properties and methods within the same code block, giving it more of a togetherness.

Not so good

The only real downside is that the private variable is limited to the scope, hence being the same for all instances. Also, it’s a bit weird to have private variables outside of the constructor.

The code execution results for all three approaches

var a = new Sub();
// Returns "Tuesday"
alert(a.getDay());

var b = new Sub();
// Returns "Tuesday"
alert(b.getDay());

// Sets dayName to "Wednesday"
a.setDay("Wednesday");

// Returns "Wednesday"
alert(a.getDay());

// Returns "Wednesday"
alert(b.getDay());

// Returns "Tuesday"
alert(b.day);

But why? The problem is that the scope each approach uses to create a private variable, which works fine, is also the closure, in action, that results in if you change a private variable for one object instance, it is being changed for all. I.e. it’s more like a private static property, than an actual private variable.

So, if you want to have something private, more like a non-public constant, any of the above approaches is good, but not for actual private variables. Private variables only work really well with singleton objects in JavaScript.

In terms of private methods, however, it works swell! You can hide away helper methods from the public eye, and then utilize it from your prototyped code.

Download the complete code

To make it easier for you, I’ve put all four code approaches in the same JavaScript file, so you can download the inheritance demo JavaScript file and play around with the code, tweak some settings, and hopefully, at the end of the day, be a more enlightened JavaScript programmer. πŸ™‚

Wrapping up

As you can see, JavaScript offers many ways to do the same thing with code, and different solutions have different advantages and disadvantages. I also think an important lesson to learn is that there’s a difference between code doing/delivering the expected results and optimal code best for runtime, execution and reusage.

Feedback

Please let me know what you thought of this experiment! I wanted to mess with your heads a little, while also opening up your mind to alternative solutions. If anything’s wrong or or not as good as it can be with the code, or if you have any solutions to the problems posed above, don’t hesitate to let me know!

18 Comments

  • Steven Clark says:

    OK, now you’ve hit awesome Robert. Here’s an idea – collate a copy of these together, say after 4-6 months and provide them (either commerically but economically, or for free) as a downloadable PDF. As a collection they are no doubt going to be quite valuable for people learning…

    Or, you could turn to whiskey and poetry and join the sad life I have on the Internet lol… hey I actually graduate from my degree next month. Temporary status. πŸ™‚

    This post must have taken you some serious amount of time.

  • Just want to refer to the Atlas guys who have switched from some kind of module pattern to prototype based inheritance. Reason number one was performance and memory consumption. A thing one need to respect in the ever growing AJAX projects.

    My 2 cents: In most cases it is completely OK to have private variables by convention e.g. through a special naming with a leading underscore etc. Only a few mashup-scenarios may require real private methods, in most other cases it does not need to be real private. More important in my opinion is good support for inheritance, for calling the super class method/constructor, for a readable syntax, …

    You may want to have a look how we deal with these topics in qooxdoo (the framework I have developed together with other brilliant guys in the last 3 years)

  • Robert? Here I am with my promised post πŸ™‚

  • Robert Nyman says:

    Steven,

    Thank you! πŸ˜€

    It’s a good idea to put them into one PDF, I just might do that! And yes, it did take some time, mostly because I wanted to test everything, truly understand, and then desperately be able to explain it in somewhat understandable terms… πŸ™‚

    Sebastian,

    Absolutely, it’s a very valid discussion whether private variables and methods are really necessary. When it comes to singleton objects, I like it for code structure and that there’s no actual performance impact, but with inheritance, one needs to ponder the gains of it.

    With you all the way about readable syntax, but in regards to super, I normally don’t find that necessary – I elaborate my standpoint more in my JavaScript inheritance article.

    Andrea,

    Thanks! Very interesting!
    It’s a delicate balance between private variable need and syntax need, but that’s a very good exercise in JavaScript and closures! πŸ™‚

  • Lars Gunther says:

    Quick tip: typo in “Everything above is probably what you expected, expect the last one that returned undefined.”

    The second “expect” should be “except” – right?

  • Robert Nyman says:

    Lars,

    Absolutely right, thanks!

  • Thanks Robert, but the most interesting thing is my next post, where I rewrite the Douglas Crockford Object.create method introducing a trick able to make every common extend method "obsolete" since we do not need to create an intermediate function every time, unless we need that closure for some other reason.

    Performances are 2 times better for both CPU and RAM in FF3, 10 times better in IE, 1.5 times better in Chrome or Opera.

    Thank you again because you let me do a couple of tests during my reply to this post which is the reason I "discovered" that trick.

    Best Regards and please do not stop with these posts πŸ˜€

  • Stefan Van Reeth says:

    Great work, Robert!!! Sure this will help out many people. I know I whish someone wrote this a few years ago. Would have saved me many wtf-moments πŸ˜€

  • Robert Nyman says:

    Andrea,

    Sounds very interesting!

    And the same goes for me! πŸ™‚

    When I write these posts I have to investigate every angle of it, and also be able to explain why and how things actually work, and that's how I learn more as well.

    I'll try and keep them coming, although most likely I'll write about other things the next posts… πŸ™‚

    Stefan,

    Thanks! And really, we've all had (and occasionally still have) the WTF moments, so don't worry. πŸ™‚

  • Steven Clark says:

    WTF moments are to web development as single malt whiskey is to… ummm web development? One famous saying that emanates from my home office quite regularly is a desperate plea of

    "But I don't understaaannnddddd…"

    Only you can probably insert swear words for about 8 sentences either side. The measurement of WTF is somewhere in the density of those swear words. πŸ™‚

  • Steven Clark says:

    Of course, I've never gotten around to inserting my "Donate quality single malt" button on my website… but that would be sooo way cool to receive even 1… mmm. I wonder if my WTF strategy would impact employability?

    Do you enjoy a tipple Robert?

  • Robert Nyman says:

    Steven,

    I know, I can totally relate to the pleading, questioning, begging, swearing… πŸ™‚

    I appreciate a tipple, but more and more seldom, to be honest. Hopefully I’m at least good company, either way. πŸ™‚

  • Jeffrey04 says:

    Just being curious, what are the differences between this way of doing closure-created constructor instead of the way you proposed in the article?

    <code>

    var Some_Class = function() {

    var private_member = 'some_value',

    private_method = function() {

    // private method implementation

    };

    if(!arguments.callee.prototype.public_method) {

    arguments.callee.prototype.public_method = function() {

    // public method implementation;

    // access private members

    private_method.call(this);

    };

    }

    // the constructor

    (function() {

    // some constructor code

    }).call(this);

    };

    </code>

    I like this way because I can put public methods to the prototype and still able to access the private members. But what are the possible drawbacks with this method?!

  • Robert Nyman says:

    Jeffrey04,

    Very interesting! I just did some basic tests on your code, but it seems to work well!

    Drawback-wise, there might be memory-consumption issues, partly from running functions within the constructor for every object instantiated, but for a few objects, I wonder if this is even noticeable.

    Good work!

  • Robert Nyman says:

    Jeffrey04,

    Yes, that is true. Good input!

    Personally, I like when people play around with it, to see what can be done. Before you know it, you stumble upon something great!

  • […] Nyman hat sich ΓΌber dieses Thema schon letztes Jahr ausgelassen. Wenn ich seinen letzten Vorschlag richtig deute, lΓΆst er auch nicht das Problem, dass […]

  • Struppi says:

    Sorry if my suggestion is already made, my english is not perfect.

    I wrote also an article about that and I came to another conclusion. I didn't test this in all browsers, but with those I did, this work perfect for this issue:

    <code>

    sub Base() {

    // same as yours

    }

    Sub.prototype = Base.prototype;

    sub Sub() {

    Base.apply(this, arguments); // arguments only if you need them

    }

    </code>

    In this way your example works perfect and every object have their own private vars. Another big pro is, that you don't need to call the constructor of Base for the prototype. I have an example to see why this could be bad.

    <code>var __ID__ = 0; // a global counter

    function Base() {

    var id = ++__ID__;

    }</code>

    If you have to use something like this, every call of new Base() increase ID, that's what you might want avoid.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.