This blog post illustrates several JavaScript inheritance topics via an example: We start with naive implementations of a constructor Point and its sub-constructor ColorPoint and then improve them, step by step. This post should be self-explanatory, but where it isn’t, you can consult the more thorough introduction to JavaScript inheritance at [1].

Constructors

Constructors are factories for objects (similar to classes in class-based languages). Every function foo can be invoked in two ways:

When we execute new Point(), the constructor’s job is to set up the fresh object passed to it via the implicit parameter this. Point() adds four properties to that object. The properties dist and toString are called
methods, because their values are functions. The object is returned by the constructor and considered its instance:

> var p = new Point(3, 1);
> p instanceof Point
true

You can invoke the methods and access the non-method properties:

> p.dist()
3.1622776601683795
> p.toString()
'(3, 1)'
> p.x
3
> p.y
1

Methods shouldn’t be in each instance, they should be shared between instances, to save memory. You can use a
prototype for that purpose: The object stored in Point.prototype becomes the prototype of the instances of Point. An object’s properties are shared by all objects that it is a prototype of, so Point.prototype is where you put the methods:

We assign an object to Point.prototype, via an
object literal that has two properties dist and toString. Now there is a clear separation of responsibility: The constructor is responsible for setting up instance-specific data, the prototype contains shared data (i.e., the methods). Note that prototypes are highly optimized in JavaScript engines, so there is usually no performance penalty for putting methods there. Methods are called just like before, you don’t notice whether they are stored in the instance or in the prototype. One problem remains: For every function f the following equation should hold
[2]:

f.prototype.constructor === f

Every function is set up like that by default. But we have replaced the default value of Point.prototype. To satisfy the equation, we can either add a property constructor to the object literal above or we can keep the default value, by not replacing it, by adding the methods to it:

Extending

In JavaScript, the term
extending an object means destructively adding new properties to it: To extend an object A with an object B, we (shallowly) copy B’s properties to A. JavaScript’s slightly uncommon definition of that term is due to the Prototype framework, which has a method
Object.extend(). The following is a naive implementation:

We do want the “own” (direct) properties x and y of the Point instance. But we don’t want its inherited properties dist and toString. Why are the inherited properties copied to the first argument? Because for-in sees all properties of an object, including inherited ones. Point inherits several properties from Object, for example valueOf:

> var p = new Point(7, 1);
> p.valueOf
[Function: valueOf]

These properties are not copied over, because for-in can only see
enumerable properties
[3] and they are not enumerable:

The failure is due to source.hasOwnProperty (line 4) accessing the own property (a number) instead of the inherited method. We can solve this problem by referring to that method directly and not via source:

Setting the prototype of an object

So far, we have seen how to add properties to an object in a destructive manner. We have also seen that prototypes do the same thing, but non-destructively: Its properties “show up” in an instance, but are not among its own properties. It would be nice if we could influence this kind of inheritance more directly and set the prototype of an object without a constructor. Given that an object’s prototype is such a fundamental, heavily optimized feature, the only standard way of doing so is by creating a new object. That is, you can only set an object’s prototype once, when you create it. The following code uses ECMAScript 5’s Object.create() to create a new object whose prototype is the object proto.

The above code uses a temporary constructor to create a single instance that has the given prototype. So far, we have ignored the optional second parameter of Object.create() that allows you to define properties on the newly created object:

The properties are defined via
property descriptors. With a descriptor, you can specify property attributes such as enumerability, not just values. As an exercise, let us implement protoChain(), a simplified version of Object.create(). It avoids the complexities of property descriptors and simply extends the new object with the second parameter. For example:

var obj = protoChain(proto, {
foo: 123,
bar: "abc"
});

We can generalize the above idea to an arbitrary amount of parameters:

protoChain(obj_0, obj_1, ..., obj_n-1, obj_n)

Remember that we have to create fresh objects in order to assign prototypes. Hence, protoChain() returns a shallow copy of obj_n whose prototype is a shallow copy of obj_n-1, etc. obj_0 is the only object in the returned chain that has not been duplicated. protoChain() can be implemented like this:

Subtyping

The idea of subtyping is to create a new constructor that is based on an existing one. The new constructor is called the sub-constructor, the existing one the super-constructor. The following is a sub-constructor of Point:

The above code sets up the instance properties x, y and color. It does so by passing this (an instance of ColorPoint) to Point: Point is called as a function, but the call() method allows us to keep the this of ColorPoint. Therefore, Point() adds x and y for us and we add color ourselves. We still need to take care of methods: On one hand, we want to inherit Point’s methods, on the other hand, we want to define our own methods. This is a simple way of doing so via extend():

We first copy the methods in Point.prototype to ColorPoint.prototype and then add our own method: We replace Point’s toString() with a version whose result combines the color with the output of Point.prototype.toString(). We directly refer to the latter method and call it with ColorPoint’s this. For more information on invoking methods of a super-prototype consult
[6]. ColorPoint works as expected:

> var cp = new ColorPoint(5, 3, "red");
> cp.toString()
'red (5, 3)'

As an improvement, we can avoid adding redundant properties to ColorPoint.prototype, by making Point.prototype its prototype.

In line 1, we have replaced the default value of ColorPoint.prototype and thus need to set the constructor property in line 2. While writing a single constructor is fairly straightforward, the above code is too complicated to be performed by hand. A helper function inherits() would make it simpler:

Conclusion

Via our running example, we have seen how to implement constructors, how to extend objects, how to set an object’s prototype and how to inherit a constructor. We have not looked at how to keep data private – that is a topic for another blog post.