JavaScript (and Backbone) Inheritance

2014/9/15 20:00

How do you determine whether an object is an instance of a class in JavaScript? The appropriately named instanceof operator is your best friend. Per the MDN entry:

The instanceof operator tests whether an object has in its prototype chain the prototype property of a constructor.

With that in mind let's run down some of the common use cases for instanceof using the native Date class:

var date = new Date(); 
date instanceof Date; // true
date instanceof Object; //true

Since instanceof checks the whole prototype chain, date instanceof Object also evaluates to true.

By a quirk in a language full of quirks instanceof won't apply to literals. For example:

var literal = 'I am a string literal',
    instantiated = new String( 'I am also a string' ); 

literal instanceof String; // false
literal instanceof Object; // false

instantiated instanceof String; // true
instantiated instanceof Object; // true

Inheritance for Instantiated User-Defined Classes

Onto a more complex example. What about custom classes that extend Backbone objects? Backbone uses the extend method to create child classes, but the instantiated objects still work with the instanceof operator.

var TestModel = Backbone.Model.extend( {} ),
    TestCollection = Backbone.Collection.extend( {} ),
    TestView = Backbone.View.extend( {} ),
    myModel = new TestModel(),
    myCollection = new TestCollection(); 

myModel instanceof TestModel; // true
myModel instanceof Backbone.Model; // true

myCollection instanceof TestCollection; // true 
myCollection instanceof Backbone.Collection; // true

Checking Inheritance for Class Definitions

But what if you want to see if a class inherits from another without having to instantiate an object? Classes in JavaScript are more of a hack, and not well supported with utility functions. Determining inheritance between two uninstantiated classes is a bit trickier, but possible.

var TestModel = Backbone.Model.extend( {} );

TestModel instanceof Backbone.Model; // false
TestModel.prototype instanceof Backbone.Model; // true

Alternatively Javscript provides an isPrototypeOf method which can also be cajoled into determining inheritance for uninstantiated classes:

var TestModel = Backbone.Model.extend( {} );

Backbone.Model.prototype.isPrototypeOf( TestModel ); // false
Backobne.Model.prototype.isPrototypeOf( TestModel.prototype ); // true