JavaScript Inheritance via Prototypes and Closures

JavaScript as a prototypical language offers loads of solutions to implement classes and class inheritance. When coming from an Object Oriented language such as Java or Ruby, these solutions aren't obvious at the first glance.

I started coding JavaScript years ago and always found a solution for my specific case. But things felt messy and I always thought "Is this really the right way of doing it?". Well, after all those years, experience took away this feeling and now I want to share some stuff that finally meant a break-through of understanding for me.

There are two different concepts of doing inheritance in JavaScript. One is using the prototype property of a function as a mean to create something similar to a "class". The other concept is using the constructor function itself to create a class dynamically during runtime.

For both concepts I'll show you their basic idea and compact helpers for creating inheritance in an elegant way.

Let's start with the prototype-based concept.

Prototype-based

In JavaScript everything is relative to a function, e.g. the scope of local variables, or the this-keyword. A class itself is also created through a simple function which in turn becomes the constructor. Every function implicitly is an object and additional properities can be added. A function automatically has a specific property: prototype which in turn is an object (or "hash") itself. This property will be used as template when a new instance is created. Here's an example:

var A = function(){}; // This is the constructor of "A"
A.prototype.constructor = A;
A.prototype.value = 1;
A.prototype.test = function() { alert(this.value); }
var a = new A(); // create an instance of A
alert(a.value);  // => 1
alert(a.test()); // => 1

The constructor of A is an empty function. You can add initializers here of course. The prototype contains a Number value and a function.

new A(); basically does all the magic. It creates a new "empty" object, copies the keys and theirs values of A.prototype into this object, and passes the object into the constructor of A accessible via the this keyword.

Let B inherit from A:

var B = function(){};
B.prototype = new A;
B.prototype.constructor = B;
B.prototype.test = function() {
  return "B says " + A.prototype.test.call(this);
};
var b = new B();
alert(b.test()); // => "B says 1"

Giving B the prototype of a new instance of A is the way to do inheritance in JavaScript. And A.prototype.method.call(this, arg1, arg2, ...); is the way to call methods of a "base class" (kind of like super.method(arg1, arg2, ...); in Java).

The advantages of using the prototype approach is speed and a low memory usage. The disadvantage is that private variables and functions cannot be shared between public methods since there's no way to create a common closure.

Closure-based

When using the closure-based approach of creating classes, the constructor of a class directly is the common closure for private variables and methods.

var C = function() {
  // a private function
  var print = function(msg) {
    alert(msg);
  };
  this.value = 1;
  this.test = function() {
    print(this.value);  // calls our private function
  };
};
var c = new C();
alert(c.value); // => 1
alert(c.test()); // => 1

Since we never assigned the prototype of C, it is an empty object. The constructor of C however "fills" each instance with values and methods by assigning them to the object itself via this.xxx = ....

Doing inheritance this way is possible but pretty ugly (especially if you want instanceof to work correctly) unless you use my closure-based helper below ;-)

Helper: prototype-based

The implicit call of a constructor when assigning a new instance of A as the prototype of B and the long winded code for calling "super" are very error prone. This makes you wish having a helper for cleaning things up. Using a helper you can do the following:

var X = PClass.create({
  val: 1,
  init: function(cv) { 
    this.cv = cv; 
  },
  test: function() { 
    return [this.val, this.cv].join(", "); 
  }
});

var Y = X.extend({
  val: 2,
  init: function(cv, cv2) { 
    this._super(cv); this.cv2 = cv2; 
  },
  test: function() { 
    return [this._super(), this.cv2].join(", "); 
  }
});

var x = new X(123);
var y = new Y(234, 567);

init is the constructor of a PClass (which stands for "Prototype-Class"). The parameters you pass to a new Xxx(...); call will be passed on to this init method.

Also note the calls to this._super(...); - this will call the base class implementation of the same method, which is much more intuitive than using ...prototype.method.call(this, ...).

The helper required to do this kind of inheritance is inspired by John Resig's solution. Here's my version of it:

(function(){
  var isFn = function(fn) { return typeof fn == "function"; };
  PClass = function(){};
  PClass.create = function(proto) {
    var k = function(magic) { // call init only if there's no magic cookie
      if (magic != isFn && isFn(this.init)) this.init.apply(this, arguments);
    };
    k.prototype = new this(isFn); // use our private method as magic cookie
    for (key in proto) (function(fn, sfn){ // create a closure
      k.prototype[key] = !isFn(fn) || !isFn(sfn) ? fn : // add _super method
        function() { this._super = sfn; return fn.apply(this, arguments); };
    })(proto[key], k.prototype[key]);
    k.prototype.constructor = k;
    k.extend = this.extend || this.create;
    return k;
  };
})();

The trick is to add a "magic cookie" to the constructor when creating the prototype for a new class. I'm using the private method isFn for that which cannot be accessed outside the closure - which in turn means that no matter what you pass in you can never mess with the mechanism ;-)

Helper: closure-based

Sometimes speed and memory are not that important for an application. But maintenance and usability are. In this case a closure-based way of doing inheritance can make sense. Having a means of private methods sometimes just "feels" better...

My helper allows you to implement inheritance in the following way (CClass stands for Closure-Class):

var Person = CClass.create(
  function(firstName, lastName) {

    // a private method
    var threeTimes = function(s) {
      return [s, s, s].join(", ");
    }

    // the public methods/fields
    return {
      // a public field
      val: 123,

      // a public method
      name: function() {
        return firstName + " " + lastName;
      },

      greet: function() {
        // call our private method and a class method
        return threeTimes("Hello " + this.name());
      }
    };
});

var Rusitschka = Person.extend(
  function(firstName) {
    // call the constructor of our base class
    this._super(firstName, "Rusitschka");

    return {
      // overwriting a field from super class
      val: 321,

      // overwriting the name method of Person
      name: function() {
        // call the base class method in our context (this)
        return "[[[" + this._super() + "]]]";
      }
    };
});

var p = new Person("Peter", "Schmidt");
var r = new Rusitschka("Steffen");
alert(p.name());  // => "Peter Schmidt"
alert(r.name());  // => "[[[Steffen Rusitschka]]]"

Just like the prototype approach you can use this._super(...); to call the base class implementation of a function. The hash object which the constructor returns automatically becomes the public interface of the class/instance.

And here's the helper that does the trick:

(function(){
  CClass = function(){};
  CClass.create = function(constructor) {
    var k = this;
    c = function() {
      this._super = k;
      var pubs = constructor.apply(this, arguments), self = this;
      for (key in pubs) (function(fn, sfn) {
        self[key] = typeof fn != "function" || typeof sfn != "function" ? fn :
          function() { this._super = sfn; return fn.apply(this, arguments); };
      })(pubs[key], self[key]);
    }; 
    c.prototype = new this;
    c.prototype.constructor = c;
    c.extend = this.extend || this.create;
    return c;
  };
})();

Summary

The two helpers PClass and CClass can help alot to implement readable and maintainable inheritance in JavaScript.

It is your choice which way of inheritance to chose for your specific problem. Speed+low memory => PClass; privacy => CClass.

And keep in mind: it is not possible to mix both concepts inside one class hierarchy.

Happy coding :-)

Trackback URL for this post:

http://www.ruzee.com/trackback/193

Getting an objects type

Hi,

I am using the helper: prototype based and was wondering if you'd found any way of getting an objects "type". I've tried modifying the code to include a className method but whatever I do can't get it to return the constructor's name as the magic function always gets returned... any pointers would be excellent!

Kind regards,

Jamie

A slightly more concise version


var Class = function(){};
Class.extend = function(proto) {
var isFn = function(fn) { return typeof fn == "function"; };
var k = function(magic) { if (magic != isFn && isFn(this.initialize)) { this.initialize.apply(this, arguments); } };
k.prototype = new this(isFn);
var makeSuper = function(fn, sfn) { return function() { this._super = sfn; return fn.apply(this, arguments); }; };
for (var key in proto) { if (proto.hasOwnProperty(key)) {
var fn = proto[key], sfn = k.prototype[key];
k.prototype[key] = !isFn(fn) || !isFn(sfn) ? fn : makeSuper(fn, sfn);
} }
k.prototype.constructor = k;
k.extend = this.extend;
return k;
};

Making it pass JSLint

Hi Steffen,

This is definitely the cleanest example of classical inheritance in javascript I've seen. Below is the amended version that passes JSLint... all seems to function correctly however would love your feedback on it:

var Class;
(function(){
var isFn = function(fn) { return typeof fn == "function"; };
Class = function(){};
Class.extend = function(proto) {
var k = function(magic) { // call init only if there's no magic cookie
if (magic != isFn && isFn(this.init)) { this.init.apply(this, arguments); }
};
k.prototype = new this(isFn); // use our private method as magic cookie
var makeSuper = function(fn, sfn) {
return function() { this._super = sfn; return fn.apply(this, arguments); };
};
for (var key in proto) {
if (proto.hasOwnProperty(key)) {
var fn = proto[key], sfn = k.prototype[key];
k.prototype[key] = !isFn(fn) || !isFn(sfn) ? fn : makeSuper(fn, sfn); // add _super method
}
}
k.prototype.constructor = k;
k.extend = this.extend;
return k;
};
})();

Prototype-Based Inheritance Example Code

In the first example is line 6 supposed to be just a.value without the alert as given in your example. I am asking because this is the second day of my study of Javascript. I loved the approach in your blog and just wondered if this was a minor detail. The code does run but produces an undefined. It seemed obvious that the code has a small problem and just wanted to know if I was right or wrong about this.
I appreciate this blog entry because it is how I wanted to learn Javascript, by starting with the basics.

Pingback

[...] JavaScript Inheritance via Prototypes and Closures | ruzee.com 8 Dec 2008. There are two different concepts of doing inheritance in JavaScript. One is using the prototype property of a function as a mean to create JavaScript Inheritance via Prototypes and Closures | ruzee.com [...]

Pingback

[...] JavaScript Inheritance via Prototypes and Closures | ruzee.com 8 Dec 2008. _super = k; var pubs = constructor.apply(this, arguments), self = this;. Pingback. Submitted by Twitter Trackbacks for JavaScript. Submitted by Dimitris Menounos (not verified) on Sun, 12/14/2008 - 11:40. JavaScript Inheritance via Prototypes and Closures | ruzee.com [...]

Pingback

[...] JavaScript Inheritance via Prototypes and Closures | ruzee.com 8 Dec 2008. _super = k; var pubs = constructor.apply(this, arguments), self = this;. Pingback. Submitted by Twitter Trackbacks for JavaScript. Submitted by Dimitris Menounos (not verified) on Sun, 12/14/2008 - 11:40. JavaScript Inheritance via Prototypes and Closures | ruzee.com [...]

Pingback

[...] JavaScript Inheritance via Prototypes and Closures | ruzee.com 8 Dec 2008. _super = k; var pubs = constructor.apply(this, arguments), self = this;. Pingback. Submitted by Twitter Trackbacks for JavaScript. Submitted by Dimitris Menounos (not verified) on Sun, 12/14/2008 - 11:40. JavaScript Inheritance via Prototypes and Closures | ruzee.com [...]

Pingback

[...] 3. JavaScript Inheritance via Prototypes and Closures [...]

Class stativ variables

Is there is a way to declare class static variables in this approach?

Thanks for great article

Yes, just form a closure

Yes, just form a closure around an anonymous hash. That will give you properly scoped class statics. Consider enclosing the constructor using the "with" statement... "with ({})"

At runtime, when you request

At runtime, when you request a property prop of an object instance, it first looks to see if that object instance has prop set. If not, it goes to object.prototype bilet

Pingback

[...] JavaScript Inheritance via Prototypes and Closures | ruzee.com - Steffen Rusitschka www.ruzee.com/blog/2008/12/javascript-inheritance-via-prototypes-and-clo... – view page – cached JavaScript as a prototypical language offers loads of solutions to implement classes and class inheritance. When coming from an Object Oriented language such as Java or Ruby, these solutions aren't obvious at the first glance. — From the page [...]

It was really happy coding :)

It was really happy coding :) This article was very helpfull. Thanks a lot.

Pingback

[...] JavaScript Inheritance via Prototypes and Closures at ruzee.com by Steffen Rusitschka (via Ajaxian) [...]

You are voted! Track back

Pingback

[...] JavaScript Inheritance via Prototypes and Closures | ruzee.com - Steffen Rusitschka (tags: programming webdev web tutorial todo) [...]

Pingback

[...] Rusitschka has a nice detailed post on inheritance with JavaScript, different ways you can go, and side effects of the [...]

Two small corrections

Nice article, though I would like to add my two points:

1) You said: "...new A(); basically does all the magic. It creates a new "empty" object, copies the keys and theirs values of A.prototype into this object, and passes the object into the constructor of A accessible via the this keyword..."

Actually it doesn't copy the keys and properties of A.prototype into the "new empty object" but a reference to the A function and its prototype. For example:

var a = new A();
a.constructor // reference to A
a.constructor.prototype // reference to A.prototype (standard)
a.__proto__ // reference to A.prototype (non-standard)

2) "var B = function() {}; B.prototype = new A();"

You need a bit more for proper inheritance. Because of point (1) B.prototype.constructor will be A. You have to set it back to B in order to make your objects play well with the "instanceof" function. Like this:

var B = function() {};
B.prototype = new A();
B.prototype.constructor = B;

Thanks ...

... for the feedback. Of course B.prototype.constructor = B; was missing - I'm doing this in both helpers already. As for the "copy vs. reference" part: It is a copy operation, otherwise modifications to B.prototype would end up in A.prototype as well...

As for the "copy vs.

As for the "copy vs. reference" part: It is a copy operation, otherwise modifications to B.prototype would end up in A.prototype as well...

No they wouldn't because "B.prototype = new A;" Or in other words:

var B = function() {};
var BP = new A();
B.prototype = BP;
B.prototype.test = function() {};

B.prototype == BP // true
B.prototype != A.prototype // true
A.prototype.test == 'undefined' // true

Dimitris is right. At

Dimitris is right.

At runtime, when you request a property prop of an object instance, it first looks to see if that object instance has prop set. If not, it goes to object.prototype.pop.

This is an important distinction for two reasons:

1) It does not allocate new memory for each property of a new object. This amounts to a huge memory save in large js architectures
2) You can modify an instance's class after the instance has been instantiated, and the change will still affect the instance.

Great article! Thanks!

Pingback

[...] Rusitschka has a nice detailed post on inheritance with JavaScript, different ways you can go, and side effects of the [...]

thanks

A very good article !

Pingback

[...] Rusitschka has a nice detailed post on inheritance with JavaScript, different ways you can go, and side effects of the [...]

thanks

i agree, very nice little tutorial which helps a lot :)

Pingback

[...] Rusitschka has a nice detailed post on inheritance with JavaScript, different ways you can go, and side effects of the [...]

This has been extremely

This has been extremely helpful! Thanks!