JavaScript has its own inheritance model that is quite unique among languages.
Since JavaScript has no notion of classes yet and since everything is actually an object, we will try to clear the confusion by defining a few terms:

  • A class is a constructor function which has properties and other functions defined on it.
  • An instance is an object created with new Class.

Instead of inheriting from a base class, instances in JavaScript inherit from a prototype object. The prototype is then referenced by every new instance of the object.
An instance can then have its own properties and methods beyond those inherited from the prototype.
JavaScript uses prototype chains: object instance C can have as prototype object instance B which in turn can have as prototype object instance A.
A property lookup traverses the prototype chain upwards.

Uses

So what are prototypes useful for?

Subclassing

The classical inheritance model found in other languages can deal with subclassing very easily. However, we can achieve subclassing in JavaScript using the prototype.

Suppose we have a parent class with a few methods declared on its prototype.

function ParentClass() {}

ParentClass.prototype = {
    firstMethod: ...
    secondMethod: ... 
};

We can then create a child class which has as its prototype set to an instance of the parent class.

function ChildClass() {}

ChildClass.prototype = new ParentClass();

If we create a new instance of each of these two classes we will notice that the child instance inherits from the parent class.

parentInstance = new ParentClass();
childInstance = new ChildClass();

> childInstance instanceof ParentClass
true

We achieved this by chaining the two classes’ prototypes. A simplified schema of the inheritance would be:

child class → child.prototype → parent class → parent.prototype

Typed Errors

Using the same pattern we can create typed errors. Errors are JavaScript’s equivalent to Exceptions found in other languages. First we need to define a constructor function.

function MyError(message) {
    this.name = 'MyError';
    this.message = message;
}

Then assign an Error instance to its prototype.

MyError.prototype = new Error();

And finally we can use it.

throw new MyError('something happened');

A nice feature of typed errors is that we can handle each error type using instanceof. A lot like the exception handling from other languages.

Only handle MyErrors and rethrow the others.

try {
    throw new MyError('something happened');
} catch (e) {
    if(e instanceof MyError) {
        ...
    } else {
        throw e;
    }
}

Read more