You are on page 1of 11

JavaScript is a bit confusing for developers experienced in class-based

languages (like Java or C++), as it is dynamic and does not provide
a class implementation per se (the classkeyword is introduced in
ES2015, but is syntactical sugar, JavaScript remains prototype-based).
When it comes to inheritance, JavaScript only has one construct: objects.
Each object has a private property (referred to as [[Prototype]] ) which
holds a link to another object called its prototype. That prototype object
has a prototype of its own, and so on until an object is reached
with null as its prototype. By definition, null has no prototype, and acts
as the final link in this prototype chain.
Nearly all objects in JavaScript are instances of Object which sits on the
top of a prototype chain.
While this is often considered to be one of JavaScript's weaknesses, the
prototypal inheritance model is in fact more powerful than the classic
model. It is, for example, fairly trivial to build a classic model on top of a
prototypal model.

Inheritance with the prototype chain
Inheriting properties
JavaScript objects are dynamic "bags" of properties (referred to as own
properties). JavaScript objects have a link to a prototype object. When
trying to access a property of an object, the property will not only be
sought on the object but on the prototype of the object, the prototype of
the prototype, and so on until either a property with a matching name is
found or the end of the prototype chain is reached.
Following the ECMAScript standard, the notation someObject.[[Prototype]]is
used to designate the prototype of someObject. Since ECMAScript 2015,
the [[Prototype]] is accessed using the
accessors Object.getPrototypeOf()and Object.setPrototypeOf(). This is
equivalent to the JavaScript property __proto__ which is non-standard but de-
facto implemented by many browsers.
It should not be confused with the func.prototype property of functions, which
instead specifies the [[Prototype]] to be assigned to all instances of objects

d). // The prototype also has a 'b' property. Here is what happens when trying to access a property: // Let's assume we have object o.created by the given function when used as a constructor. // by definition.prototype property represents the Object prototype object. and its value is 2. // Thus. but it's not visited.log(o. // This is called "property shadowing. console. // undefined // Is there a 'd' own property on o? No. The Object. check its prototype. // 1 // Is there an 'a' own property on o? Yes. with its own properties a and b: // {a: 1. // 2 // Is there a 'b' own property on o? Yes.b). b: 2} // o. .log(o." console. as null. has no [[Prototype]]. // Is there a 'c' own property on o.log(o.[[Prototype]]. console.[[Prototype]]? Yes.c). its value is 4.a).log(o. b: 2} ---> {b: 3. c: 4} ---> null console.[[Prototype]] has properties b and c: // {b: 3.[[Prototype]] is null. the full prototype chain looks like: // {a: 1. c: 4} // Finally. o. // 4 // Is there a 'c' own property on o? No. check its prototype. and its value is 1. // This is the end of the prototype chain.

check its prototype.log(o. } }. // 3 // When calling o.a + 1. return undefined.log(p. console. a form of method overriding).create(o). // creates an own property 'a' on p console.m()). Inheriting "methods" JavaScript does not have "methods" in the form that class-based languages define them.m()). // 5 . The only exception to the getting and setting behavior rules is when there is an inherited property with a getter or a setter. m: function() { return this. // p is an object that inherits from o p. var o = { a: 2. An inherited function acts just as any other property.[[Prototype]] is null. // no property found. not to the prototype object where the function is an own property.a = 4.// Is there a 'd' own property on o. the value of this points to the inheriting object. Setting a property to an object creates an own property. any function can be added to an object in the form of a property. including property shadowing as shown above (in this case. // o. stop searching.[[Prototype]]? No. In JavaScript.m in this case. 'this' refers to o var p = Object.[[Prototype]]. When an inherited function is executed.

'this' refers to p. // o ---> Object. // So when p inherits the function m of o. // 'this.prototype ---> null var b = ['yo'.prototype ---> null .) // The prototype chain looks like: // b ---> Array. 'whadup'.) // f ---> Function.prototype has null as its prototype.a. // Arrays inherit from Array. // The newly created object o has Object.// when p. forEach.prototype // (which has methods indexOf. } // Functions inherit from Function. etc.prototype ---> null function f() { return 2.prototype ---> Object. bind.a' means p. // So o inherits hasOwnProperty from Object.prototype ---> Object. '?']. etc.prototype.prototype // Object.prototype // (which has methods call.m is called.prototype as its [[Prototype]] // o has no own property named 'hasOwnProperty' // hasOwnProperty is an own property of Object. the own property 'a' of p Different ways to create objects and the resulting prototype chain Objects created with syntax constructs var o = {a: 1}.

create(a). this. Calling this method creates a new object.create(b). // a ---> Object. // g is an object with own properties 'vertices' and 'edges'.prototype = { addVertex: function(v) { this. } Graph.vertices.log(b. // 1 (inherited) var c = Object. } }. // c ---> b ---> a ---> Object.prototype when new Graph() is executed.vertices = [].prototype ---> null .create ECMAScript 5 introduced a new method: Object.prototype ---> null console.push(v). var g = new Graph().a). With Object.edges = []. // g.With a constructor A "constructor" in JavaScript is "just" a function that happens to be called with the new operator.create(). // b ---> a ---> Object. function Graph() { this.[[Prototype]] is the value of Graph. The prototype of this object is the first argument of the function: var a = {a: 1}.prototype ---> null var b = Object.

log(d.create(null).var d = Object.height = height.height = newLength. width) { this.width = width. static.height * this. extends. this. // d ---> null console. and super. constructor. class Polygon { constructor(height.hasOwnProperty).width.width = newLength. because d doesn't inherit from Object. } get area() { return this. // undefined.prototype With the class keyword ECMAScript 2015 introduced a new set of keywords implementing classes. they are not the same. } set sideLength(newLength) { this. this. sideLength). 'use strict'. Although these constructs look like those familiar to developers of class-based languages. The new keywords include class. } } class Square extends Polygon { constructor(sideLength) { super(sideLength. } } . JavaScript remains prototype-based.

// true hasOwnProperty is the only thing in JavaScript which deals with properties and does nottraverse the prototype chain. // true console. Performance The lookup time for properties that are high up on the prototype chain can have a negative impact on performance. // false console.__proto__.hasOwnProperty('addVertex')).log(g. when iterating over the properties of an object. The property might very well exist. let's take the above graph example code to illustrate it: console. Additionally.log(g. To check whether an object has a property defined on itself and not somewhere on its prototype chain.hasOwnProperty('nope')). // false console. Also.hasOwnProperty('addVertex')).log(g.var square = new Square(2). trying to access nonexistent properties will always traverse the full prototype chain. To give you a concrete example. but its value just happens to be set to undefined. .log(g. and this may be significant in code where performance is critical.prototype. it is necessary to use the hasOwnProperty method which all objects inherit from Object. Note: It is not enough to check whether a property is undefined. every enumerable property that is on the prototype chain will be enumerated.hasOwnProperty('vertices')).

The only good reason for extending a built-in prototype is to backport the features of newer JavaScript engines. like Array.Bad practice: Extension of native prototypes One mis-feature that is often used is to extend Object. While used by popular frameworks such as Prototype..prototype or one of the other built-in prototypes.varA = a.prototype = { varA: null.varA will always be shadowed by // this. Example B shall inherit from A: function A(a) { javascript#Initializing-instance-variables // would be valid if varA wasn't being initialized uniquely for each instance doSomething: function() { // } // What is the purpose of including varA in the prototype when A. // Shouldn't we strike varA from the prototype as doing nothing? // perhaps intended as an optimization to allocate space in hidden classes? // https://developers. given the definition of function A above? A.forEach. This technique is called monkey patching and breaks encapsulation. there is still no good reason for cluttering built-in types with additional non- standard functionality.js.prototype. .varA.

this.varB = b.create(A. writable: true }.. var b = new B().doSomething. arguments). b) { A. a).apply(this. enumerable: true.prototype.prototype = function B(a. } B. configurable: true. } }. { varB: { value: null. writable: true } }). B. configurable: true.doSomething().. enumerable: true. The important parts are: . b.prototype.prototype.constructor = B. // call super // . doSomething: { value: function() { // override A. }.

doSomething. i. and it has no classes at all. •You use Object. if you wanted to. [[Prototype]] = A. prototype and Object.getPrototypeOf(Object. Object.getPrototypeOf(a1). Even the "classes" we simulate are just a function object.doSomething.prototype.getPrototypeOf(a1). In short. For example. This special property works with the JavaScript new operator.getPrototypeOf returns null.e. as it's all dynamic. You probably already noticed that our function A has a special property called prototype. It's all just instances (objects).getPrototypeOf(a1). This means that all the stuff you define in prototype is effectively shared by all instances. then a1.getPrototypeOf(a1)). it looks in [[Prototype]]. all runtime. and you can even later change parts of prototype and have the changes appear in all existing instances.doSomething == Object.doSomething would actually refer to Object. The reference to the prototype object is copied to the internal [[Prototype]] property of the new instance. JavaScript (after creating the object in memory and before running function A() with this defined to it) sets a1. [[Prototype]] is looked at recursively.create() to inherit. prototype is for types.prototype. you do var a1 = new A(). in the example above. When you then access properties of the instance.doSomething. Object .doSomething == A. while Object. .getPrototypeOf(a2). a1.doSomething you defined. until it's found or Object. If. when you do var a1 = new A(). and if not.e.doSomething. JavaScript first checks whether they exist on that object directly.getPrototypeOf() is the same for instances.doSomething etc. i. var a2 = new A().getPrototypeOf JavaScript is a bit confusing for developers coming from Java or C++.prototype. Object.•Types are defined in . which is the same as the A..prototype.

o. it checks Object.[[Prototype]] = Foo.someProp. In conclusion It is essential to understand the prototypal inheritance model before writing complex code that makes use of it.prototype. If not. Further. (or something like that) and when you later do o.getPrototypeOf(o)). it checks whether o has a property someProp.So. and if that doesn't exist it checks Object. be aware of the length of the prototype chains in your code and break them up if necessary to avoid possible performance problems. when you call var o = new Foo().getPrototypeOf(Object.getPrototypeOf(o). and so JavaScript actually just does var o = new Object(). Also. the native prototypes should never be extended unless it is for the sake of compatibility with newer JavaScript features.someProp.someProp . Foo. .