Prototypal Inheritance in JavaScript

As anyone who has tried will know, inheritance is really awful in JavaScript. I just watched a really good video from Douglas Crockford that shows how to make prototypal inheritance work well in JavaScript. First, there are two ways to do OOP:

Classical
Essentially every OOP language other than JavaScript. You have “Classes” and each object is a member of a class. For example, Alice might be an object of the class Person.
Prototypal
There are no classes, just objects. Inheritance means “make an object based on this other object and then make these changes”. For example, you might have the object Person, and you create Alice by making it just like Person, but with a specific name.

The problem with JavaScript is not that it is prototypal, but rather that Netscape tried to make a prototypal inheritance that looked classical, and it got neither right. But here is a way to make prototypal inheritance in JS, curtesy of Crockford:

/* This is where the magic happens. */
function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}
var Alice = {
    name: "Alice",
    run: function() {document.write("Run! Run! Run!")}
};

var Bob = object(Alice);

Here, Alice is just a regular JavaScript object. It has one property and one method. Notice that there is no constructor. To learn why this works, watch Doug’s video.

Right now Bob inherits from Alice. It has the same properties and methods. But we can customize Bob:

Bob.name = "Bob";
Bob.hobbies = ["Science Fiction", "Archery"];

We replaced the name property and add a new property to Bob. But Bob and Alice still share the run() method. But watch this: We can add a new property to Alice, after we created Bob, and Bob will inherit that property also:

Alice.job = "Cryptographer";

Now Bob also has the attribute job, with the value “Cryptographer”, courtesy of Alice.

Private properties

This is where things begin to get uglier. To get private properties in JavaScript you need to use closures (ie. anonymous functions). For example, like this:

var Jimmy = (function() {
    var age = 10;
    return {
        birthDay: function() { age += 1; return age;},
        getAge: function() {return age},
        name: "Jimmy"
    };
})();

What’s happened here is that we made an anonymous function and immediately executed it. The variable age is local to that function, and so it is private. But because it is referenced by the methods, it is not destroyed when we exit the function.

We can also use a closure to get private properties in a child object:

var Sarah = (function() {
    var age = 8;
    var that = object(Jimmy);
    that.birthDay = function() { age += 1; return age; };
    that.name = "Jimmy";
    return that;
})();

Notice that Sarah still has the getAge() method, but that this method still points to the old age variable in Jimmy.

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>