Javascript Object Oriented Design - Javascript Prototypes








When using constructors to create objects, each instance has had its own writeLine() method.

If we have 100 instances of book, there are 100 copies of writeLine method.

We can use prototypes to have only one copy of the method.

That prototype is shared among all of the object instances, and those instances can access properties of the prototype.

We can determine whether a property is on the prototype by using a function such as:


function Book(name) { /*from   w w  w .  j  a v a  2  s  . co m*/
   this.name = name; 
   this.writeLine = function() { 
        console.log(this.name); 
    }; 
} 

var book = new Book("Javascript"); 

function hasPrototypeProperty(object, name) { 
    return name in object && !object.hasOwnProperty(name); 
} 

console.log(hasPrototypeProperty(book, "name"));             // false 
console.log(hasPrototypeProperty(book, "hasOwnProperty"));    // true 

The code above generates the following result.

If the property is in an object but hasOwnProperty() returns false, then the property is on the prototype .





The [[Prototype]] Property

An instance keeps track of its prototype through an internal property called [[Prototype]].

When creating a new object using new, the constructor's prototype property is assigned to the [[Prototype]] property of that new object.

We can read the value of the [[Prototype]] property by using the Object.getPrototypeOf() method on an object.

For example, the following code checks the [[Prototype]] of a generic, empty object.


var object = {}; 
var prototype = Object.getPrototypeOf(object); 

console.log(prototype === Object.prototype);            // true 

We can also test to see if one object is a prototype for another by using the isPrototypeOf() method, which is included on all objects:


var object = {}; 

console.log(Object.prototype.isPrototypeOf(object));    // true 

When a property is read on an object, the JavaScript engine first searches for an own property with that name.

If the engine finds a correctly named own property, it returns that value.

If no own property with that name exists on the target object, JavaScript searches the [[Prototype]] object instead.

If a prototype property with that name exists, the value of that property is returned.

If the search concludes without finding a property with the correct name, undefined is returned.





Note

Consider the following, in which an object is first created without any own properties:


var object = {}; 
/*from  www.  j  av  a2 s . c o m*/
console.log(object.toString());    // "[object Object]" 

object.toString = function() { 
    return "[object Custom]"; 
}; 

console.log(object.toString());    // "[object Custom]" 

// delete own property 
delete object.toString; 
console.log(object.toString());    // "[object Object]" 

// no effect - delete only works on own properties 
delete object.toString; 
console.log(object.toString());    // "[object Object]" 

The code above generates the following result.

We cannot assign a value to a prototype property from an instance.

Assigning a value to toString creates a new own property on the instance, leaving the property on the prototype untouched.