I thought I’d share a few of the key points that helped me understand how objects, classes and inheritance work in javascript, along with an example of “class-like” inheritance.

A different approach to “new”

First, where most of the object-oriented languages I’ve come across use classes, javascript uses prototypes instead.

  • In class-based languages, new objects are created by using the keyword “new”, followed by the name of the class and the arguments to be passed in to the constructor function of that class.
  • In javascript, new objects are created using keyword “new”, followed by the constructor function itself, with the arguments to be passed to it.

Constructor functions in javascript are just regular functions, but commonly if we design a function to be used as an object constructor, we capitalise the first letter of the function name.

So for example:

function Rectangle(w, h) {
 this.width = w;
 this.height = h;
 this.area = w * h;
}
var myRectangle = new Rectangle(5, 3);
myRectangle.area; //Returns 15;

Because we used the “new” keyword, a new object is created, and the function “Rectangle” is called with the keyword “this” referring to the new object. If the constructor function returns something, that’s what the “new” keyword will return, but if it doesn’t then the newly created object will be returned instead.

Functions are objects, too

The next thing thing I needed to learn was that in javascript, functions are basically just a special type of object – not only can you “call” them, but you can also pass them by reference, and they have properties and methods of their own.

Prototypes – what they are

One of those properties is called “prototype”, and whenever a new function is defined, a new object is created and assigned to the prototype property of that function. The object is almost empty – it has a property called “constructor”, which refers to the function for which it was created, but that’s about it. You can add properties and methods to that object, though, and this comes in handy because of one more thing that the “new” keyword does.

When a function is called with the “new” keyword, the prototype property of that function defines properties and methods to be inherited by the newly created object.

So for example:

function Rectangle(w, h) {
this.width = w;
this.height = h;
}
Rectangle.prototype.sides = 4;
Rectangle.prototype.area = function() {
return this.w * this.h;
}

var myRectangle = new Rectange(2, 5);
myRectangle.width; //Returns 2
myRectangle.sides; //Returns 4
myRectangle.area(); //Returns 10

Prototypes – how they work

This inheritance is carried out by having new objects store a reference to the prototype object – so if the prototype is modified, all the objects sharing that prototype will be affected. When you attempt to get a property of an object, javascript will first look to see if that property has been set locally for that object, and if it hasn’t, it will attempt to get the property from the object’s prototype instead.

This can result in javascript following  a “chain” of prototypes, if the object’s prototype has a prototype of it’s own. Each prototype only exist once in memory, though; They are linked together by references.

Jumping ahead…

I’d like to finish off (for now) with an example of how I write class-like inheritance in javascript. I’m using an immediately-invoked function expression to create a closure, and a function called “heir”* to handle prototype chaining, and a variable called “superProto” to implement the kind of functionality that languages like Java provide with the “super” keyword:

function heir(p) {
 // This function creates a new empty object that inherits from p
 var f = function(){};
 f.prototype = p;
 return new f();
}

// Class "Shape"
Shape = function(color) {
 this.color = color;
}
Shape.prototype.draw = function(){
 alert('Cannot draw a shape...');
}
Shape.prototype.whatAmI = function(){
 alert("I'm a shape");
}
Shape.prototype.isRed = function(){
 return this.color === "Red";
}

// Class "Rectangle"
var Rectangle;
(function(){
 var superProto = Shape.prototype;
 Rectangle = function(color, width, height){ // The constructor function
  superProto.constructor.call(this, color);
  this.width = width;
  this.height = height;
 }

 Rectangle.prototype = heir(superProto); // These 2 lines handle the inheritance
 Rectangle.prototype.constructor = Rectangle;

 Rectangle.prototype.draw = function(){ // Other methods of class "Rectangle"
  superProto.draw.call(this);
  alert('...not even a rectangle...');
 }
 Rectangle.prototype.whatAmI = function(){
  alert("I'm a rectangle");
 }
 Rectangle.prototype.area = function(){
  return this.width * this.height;
 }
})();

// Some testing
var rect = new Rectangle("Red", 5, 3);
rect.isRed(); //Returns true
rect.area(); //Returns 15
rect.draw(); //Alerts "Cannot draw a shape..." and "...not even a rectangle..."
rect.whatAmI(); //Alerts "I'm a rectangle"

jsfiddle of example

*(Since writing this post, I have learnt that newer browsers may support “Object.create”, which provides the same functionality as “heir”, and more besides.)