This page is Not Ready

Notice: The WebPlatform project, supported by various stewards between 2012 and 2015, has been discontinued. This site is now available on github.

Prototypes

Summary

JavaScript is a little confusing for developers experienced in class-based languages (like Java or C++), as it’s dynamic and does not provide a class implementation (although the keyword class is a reserved keyword and cannot be used as a variable name).

JavaScript is still an Object Orientated Language (OOP), meaning you can construct class like structures and instantiate them into objects that are used in the same way as class-based languages.

An object has an internal link to another object (or null) called its prototype. This object has a prototype as well and so on, until one object has null as its prototype. This chain of objects being prototypes of one another is called the prototype chain.

Inheritance with the prototype chain

Inheriting properties

JavaScript objects are dynamic “bags” of properties (referred as own properties) and have a link to a prototype object (or null). Here is what happens when trying to access a property:

// Let's assume we have an object o with its prototype chain looking like:
 // {a:1, b:2} ---> {b:3, c:4} ---> null
 // 'a' and 'b' are o own properties.

 // In this example, someObject.[[Prototype]] will designate the prototype of someObject.
 // This is a pure notation (based on the one used in the ECMAScript standard) and cannot be used in scripts

 console.log(o.a); // 1
 // Is there an 'a' own property on o? Yes and its value is 1

 console.log(o.b); // 2
 // Is there a 'b' own property on o? Yes and its value is 2
 // The prototype also has a 'b' property, but it's not visited. This is called "property shadowing"

 console.log(o.c); // 4
 // Is there a 'c' own property on o? No, check its prototype
 // Is there a 'c' own property on o.[[Prototype]]? Yes, its value is 4

 console.log(o.d); // undefined
 // Is there a 'd' own property on o? No, check its prototype
 // Is there a 'd' own property on o.[[Prototype]]? No, check it prototype
 // o.[[Prototype]].[[Prototype]] is null, stop searching, no property found, return undefined

Setting a property to an object creates an own property. The only exception to the getting and setting behavior rules is when there is an inherited property with a defining getters and setters getter or a setter.

Inheriting “methods”

JavaScript does not have “methods” per se. JavaScript has functions and these functions can be used as property values. The inheritance of functions works the same way that any value, including property shadowing as shown above (which is a form of method overriding).

The only thing that changes when functions are object properties (own or inherited) is the value of this when the function is executed.

var o = {
   a: 2,
   m: function(b){
     return this.a + 1;
   }
 };

 console.log(o.m()); // 3
 // When calling o.m in this case, 'this' refers to o.

 var p = Object.create(o);
 // p is an object and p.[[Prototype]] is o

 p.a = 12; // creates an own 'a' property on p.
 console.log(p.m()); // 13
 // when p.m is called, 'this' refers to p. 'this.a' is p own property

Different ways to create objects and the resulting prototype chain

Objects created with syntax constructs

var o = {a: 1};

 // This object is created with Object.prototype as its [[Prototype]]
 // This is what allows to call o.hasOwnProperty('a').
 // hasOwnProperty is an own property of Object.prototype
 // Object.prototype has null as its prototype.
 // o ---> Object.prototype ---> null

 var a = ["yo", "whadup", "?"];

 // Arrays inherits from Array.prototype (which has methods like indexOf, forEach, etc.).
 // The prototype chain looks like:
 // a ---> Array.prototype ---> Object.prototype ---> null

 function f(){
   return 2;
 }

 // Functions inherit from Function.prototype (which has methods like call, bind, etc.):
 // f ---> Function.prototype ---> Object.prototype ---> null

With a constructor

A “constructor” in JavaScript is “just” a function that happens to be called with the new operator.

function Graph() {
   this.vertexes = [];
   this.edges = [];
 }

 Graph.prototype = {
   addVertex: function(v){
     this.vertexes.push(v);
   }
 };

 var g = new Graph();
 // g is an object with own properties 'vertexes' and 'edges'.
 // g.[[Prototype]] is value of Graph.prototype at time of instantiation.

With Object.create

ECMAScript 5 introduced a new method: Object.create. Calling this method creates a new object. The prototype of this object is the first argument of the function:

var a = {a: 1};
// a ---> Object.prototype ---> null

var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (inherited)

var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null

var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty); // undefined, because d doesn't inherit from Object.prototype

Attributions

  • This article contains content originally from external sources, including ones licensed under the CC-BY-SA license. cc-by-sa-small-wpd.png

  • Portions of this content copyright 2012 Mozilla Contributors. This article contains work licensed under the Creative Commons Attribution-Sharealike License v2.5 or later. The original work is available at Mozilla Developer Network: Article