I’m continuing this series on Javascript concepts for people new to the language by looking at object oriented programming. One of the more confusing concepts for new Javascript programmers, especially those used to the classical inheritance structures of Java or C++ is Javascript’s prototypical inheritance model. Because it is possible to write syntax for Javascript object creation that can look very similar to classical inheritance in Java, its easy to be misled and have false expectations. Its important to understand how Javascript’s object model works, so that you can adjust your expectations and write code that takes advantage of the language’s expressive power.
Creating a new object
Javascript provides multiple ways to create new objects. The simplest way is to just create an empty object with {}
. The one I’ll be looking at today was modeled after Java syntax and gives the language a deceptively classical vibe:
//Creating Objects with new
function Animal(){
this.home = "earth";
this.noise = "roar";
}
Animal.prototype.sound = function(){
alert(this.noise);
}
var animalObject = new Animal();
animalObject.sound(); // roar
var home = animalObject.home //earth
This all looks very familiar and comfortable to a Java programmer. Animal() is the constructor of a class Animal, with a function sound() and animalObject is an instance of that class. And you can write code like that if you want. The problem is, that model is not enforced at all by javascript. Javascript doesn’t have any special “constructor functions” or classes1. Any function can be used as a constructor
//Normal Function as constructor
function normalFunc(){
alert("This is a normal function")
}
var normal = new normalFunc();
normal instanceof normalFunc //true
var x = {};
x.y = normalFunc;
var huh = new x.y();
huh instance of normalFunc //true
So whats actually happening when you call new before a function? The new operator generates a new object, binds this
to that object for the constructor function, calls that function and sets that function as the prototype of the new object. But what is a prototype?
Prototypes
Javascript inheritance is at its heart “prototypical inheritance”. This means that rather than having a concept of “classes” and “implementations” of those classes, javascript objects inherit their properties directly from other objects. So for the “classical” example above, what is actually happening is that a new object is being created, it is having some of its properties set by the constructor function, and then has the constructor’s prototype set as its prototype. This means that it has access to any properties on the “prototype chain” of the constructor, which in this case includes the sound method. All objects have acccess to Object.prototype, giving it access to object properties and methods like toString, hasOwnProperty and others.
The ES5 Way
The ECMAScript 5 specification defines a new way to create objects from existing objects with the Object.create() syntax. Object.create takes an existing object and sets it as the prototype object for a newly created object2. This was added to make the syntax for setting the prototype of a new object easier and more clear.3 It also allows us to simulate classical inheritance:
//ES5 Classical Inheritance example
var Cat = function(){
Animal.call(this); //Call the Animal constructor to set local variables
this.noise = "meow" //override the Animal sound
}
Cat.prototype = Object.create(Animal.prototype)
var kitty = new Cat();
kitty.sound() //meow
alert(kitty.hasOwnProperty("sound")) //false
alert(kitty instanceof Cat) //true
alert(kitty instanceof Animal) //true
So as you can see, it is very possible to write Object-Oriented Javascript. The key is to understand that what’s happening behind the scenes in Javascript is different than Java or C++, even though the syntax may look similar.
Summary
-
Inheritance and object oriented programming in javascript are possible, but are more of a programmer defined construct rather than an inherent property of the language
-
Javascript supports prototypical inheritance, meaning that it inherits functions and properties from its prototype object. All objects inherit from Object.prototype.
-
ECMAScript 5 introduced support for Object.create, which provides an easier syntax for creating new objects and simulating inheritance.
Further Reading
-
Mozilla’s Developer Documentation has a good summary of implementing Object Oriented Programming concepts in Javascript
-
Managing Javascript Objects is a great article by Nicholas Zakas for MSDN about designing an object oriented application in Javascript. Zakas also has recently written a book on object oriented programming in Javascript
Explaining Javascript
This is the second article in my Explaining Javascript series for introducing Javascript concepts to new JS developers.
-
In the next version of Javascript ES6 there will be a more formal concept of classes. You can read more here if interested ↩
-
With an optional second argument to set the local properties of the object from another object. Note that these properties will need to be Objects, not primitive values, or a TypeError will be thrown ↩
-
Thanks to Eric Elliot for pointing out that my original description of Object.Create was misleading. There are multiple ways to create and reuse object code in Javascript. I only touch on one of them in this article.
↩