Object JavaScript – Understanding Prototypes, Inheritance

10063_580983808600819_401360548_nJavaScript is full of objects. In the previous posting, you learned how to create objects using constructors and literals. You saw a couple notations for creating objects. You learned how to add properties and methods.

In this lesson, you will learn about prototypes. A prototype is an object from which other objects inherit properties.

Every object has a prototype by default. Since prototypes are themselves objects, every prototype has a prototype too. (There is only one exception, the default object prototype at the top of every prototype chain.)

Object Review

An object in JavaScript is any unordered collection of key-value pairs. If it’s not a primitive (undefined, null, boolean, number, or string) — it’s an object.

In our last post, you learned how to create an object with properties and methods, and then use the new keyword to creates instances of the object. Here’s an example:


function Cat(name) {
this.name = name;
this.talk = function() {
console.log( this.name + " says meeow!" );
}
}
var cat1 = new Cat("felix");
cat1.talk(); //sends "felix says meeow!" to the console
var cat2 = new Cat("ginger");
cat2.talk(); // sends "ginger says meeow!" to the console

view raw

ojs-review.js

hosted with ❤ by GitHub

The function Cat() acts as an object constructor. Its properties and methods are declared inside it by prefixing them with the keyword this. Objects defined using an object constructor are then instantiated using the new keyword. Now you can easily define multiple instances of Cat, each with its own name.

Prototype Concepts

The name prototype comes from the idea that in JavaScript, an object is created as a copy of an existing example (that is, a prototype) object. Any properties and methods of this prototype object will appear as properties and methods of the objects created from that prototype’s constructor. You can say that these objects inherit their properties and methods from their prototype.

In JavaScript, every function has a property named prototype that refers to a prototype object. This prototype object in turn has a property named “constructor,” which refers back to the function itself. It’s sort of a circular reference.

image

 

Now, when a function (in the example above, Dog) is used to create an object with the “new” operator, the resulting object will inherit the properties of Dog.prototype. See that the Dog.prototype object has a constructor property that points back to the Dog function. Consequently, every Dog object (that inherits from Dog.prototype) will also appear to have a constructor property that points back to the Dog function.


var spot = new Cat("Spot");
// Cat.prototype is the prototype of spot
console.log(Cat.prototype.isPrototypeOf(spot));
// spot inherits the constructor property from Cat.prototype
console.log(spot.constructor == Cat.prototype.constructor);
console.log(spot.constructor == Cat);
// But constructor property doesn’t belong to spot. The line below displays "false"
alert(spot.hasOwnProperty("constructor"));

view raw

ojs-newdog.js

hosted with ❤ by GitHub

Creating Multiple Cat Instances Using Prototype

Suppose we want to add another function to Cat, after we have defined it. Prototype is a type of inheritance in JavaScript.

image

Use it when you want an object to inherit a method after it has been defined. You can think of prototyping as “attaching” a method to an object after it’s been defined. And all object instances will then instantly share  this new behavior.

Our example continue from the previous code:


Cat.prototype.changeName = function(name) {
this.name = name;
}
var firstCat = new Cat("cc");
firstCat.changeName("bill");
firstCat.talk() //will now send "bill says meeow!" to the console

view raw

ojs-prototype

hosted with ❤ by GitHub

In JavaScript, every function has a property named prototype that refers to a prototype object.

You can get the prototype using getPrototypeOf() and you can determine if two objects have the same prototype:


Object.getPrototypeOf("felix") === Object.getPrototypeOf("ginger");

Chain of Prototypes

Every JavaScript object inherits a chain of prototypes, all of which terminate with Object.prototype.

It is done using a simple algorithm, as follows: when you try to access a property/method of an object, JavaScript checks if that property/method is defined in that object. If not, then the object’s prototype will be checked. If not, then that object’s prototype’s prototype will be checked, and so on, all the way to Object.prototype.

image

Instead of having a separate instance of a function object for every object, you can make the objects share the method by putting it inside the prototype.

Property Access Errors

It is not an error to query a property that does not exist. If a particular property is not found as its own property or an inherited property, the property access expression o.x evaluates to undefined.

For example, if I am to call see if I can get spot’s mother’s name, the value will be returned as undefined.


var motherName = spot.mother.name;

This raises  a TypeError exception. Unless you are certain the property exists, you should test to be sure properties exist.


// Here’s a verbose technique:
var motherName = undefined;
if(spot) {
if (spot.mother) motherName = spot.mother.name;
}
// And here is a more concise way.
var motherName = spot && spot.mother && spot.mother.name;

Object.create

Inheritance is a way to create a class as a specialized version of one or more classes (JavaScript only supports single class inheritance). The specialized class is commonly called the child, and the other class is commonly called the parent. In JavaScript you do this by:

Assigning an instance of the parent class to the child class, and then specializing it.

In modern browsers you can also use Object.create() to implement inheritance by passing in the prototype.

Here is an example of creating an object that has the same internal prototype as the Shape object.


// Create the shape object.
var Shape = { twoDimensional: true, color: undefined, hasLineSegments: undefined };
var Square = Object.create(Object.getPrototypeOf(Shape));

References