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 keyword is introduced in ES2015, but is syntactical sugar, JavaScript remains prototype-based). class When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property which holds a link to another object called its . That prototype object has a prototype of its own, and so on until an object is reached with as its prototype. By definition, has no prototype, and acts as the final link in this . prototype null null prototype chain Nearly all objects in JavaScript are instances of which sits on the top of a prototype chain. Object While this confusion is often considered to be one of JavaScript's weaknesses, the prototypal inheritance model itself 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 JavaScript objects are dynamic "bags" of properties (referred to as ). 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. Inheriting properties own properties Following the ECMAScript standard, the notation is used to designate the prototype of . Since ECMAScript 2015, the is accessed using the accessors and . This is equivalent to the JavaScript property which is non-standard but de-facto implemented by many browsers. someObject.[[Prototype]] someObject [[Prototype]] Object.getPrototypeOf() Object.setPrototypeOf() __proto__ It should not be confused with the property of functions, which instead specifies the to be assigned to all of objects created by the given function when used as a constructor. The property represents the prototype object. func .prototype [[Prototype]] instances Object.prototype Object Here is what happens when trying to access a property: f = { .a = ; .b = ; } o = f(); f.prototype.b = ; f.prototype.c = ; .log(o.a); .log(o.b); .log(o.c); .log(o.d); // Let's create an object o from function f with its own properties a and b: let ( ) function this 1 this 2 let new // {a: 1, b: 2} // add properties in f function's prototype 3 4 // do not set the prototype f.prototype = {b:3,c:4}; this will break the prototype chain // o.[[Prototype]] has properties b and c. // o.[[Prototype]].[[Prototype]] is Object.prototype. // Finally, o.[[Prototype]].[[Prototype]].[[Prototype]] is null. // This is the end of the prototype chain, as null, // by definition, has no [[Prototype]]. // Thus, the full prototype chain looks like: // {a: 1, b: 2} ---> {b: 3, c: 4} ---> Object.prototype ---> null console // 1 // Is there an 'a' own property on o? Yes, and its value is 1. console // 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 // 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 // undefined // Is there a 'd' own property on o? No, check its prototype. // Is there a 'd' own property on o.[[Prototype]]? No, check its prototype. // o.[[Prototype]].[[Prototype]] is Object.prototype and there is no 'd' property by default, check its prototype. // o.[[Prototype]].[[Prototype]].[[Prototype]] is null, stop searching, // no property found, return undefined. Code Link 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 . getter or a setter JavaScript does not have "methods" in the form that class-based languages define them. In JavaScript, any function can be added to an object in the form of a property. An inherited function acts just as any other property, including property shadowing as shown above (in this case, a form of ). Inheriting "methods" method overriding When an inherited function is executed, the value of points to the inheriting object, not to the prototype object where the function is an own property. this var o = { a: , m: function() { .a + ; } }; console. (o.m()); var p = Object.create(o); p.a = ; console. (p.m()); 2 return this 1 log // 3 // When calling o.m in this case, 'this' refers to o // p is an object that inherits from o 4 // creates a property 'a' on p log // 5 // when p.m is called, 'this' refers to p. // So when p inherits the function m of o, // 'this.a' means p.a, the property 'a' of p Using prototypes in JavaScript Let's look at what happens behind the scenes in a bit more detail. In JavaScript, as mentioned above, functions are able to have properties. All functions have a special property named . Please note that the code below is free-standing (it is safe to assume there is no other JavaScript on the webpage other than the below code). For the best learning experience, it is highly recommended that you open a console, navigate to the "console" tab, copy-and-paste in the below JavaScript code, and run it by pressing the Enter/Return key. (The console is included in most web browser's Developer Tools. More information is available for , , and .) prototype Firefox Developer Tools Chrome DevTools Edge DevTools {} console. ( doSomething.prototype ); var doSomething = function(){}; console. ( doSomething.prototype ); function doSomething () log // It does not matter how you declare the function, a // function in JavaScript will always have a default // prototype property. // (Ps: There is one exception that arrow function doesn't have a default prototype property) log As seen above, has a default property, as demonstrated by the console. After running this code, the console should have displayed an object that looks similar to this. doSomething() prototype { constructor: ƒ doSomething(), __proto__: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } } We can add properties to the prototype of , as shown below. doSomething() {} doSomething.prototype.foo = ; console. ( doSomething.prototype ); function doSomething () "bar" log This results in: { foo: , constructor: ƒ doSomething(), __proto__: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } } "bar" We can now use the operator to create an instance of based on this prototype. To use the new operator, simply call the function normally except prefix it with new. Calling a function with the operator returns an object that is an instance of the function. Properties can then be added onto this object. new doSomething() new Try the following code: {} doSomething.prototype.foo = ; var doSomeInstancing = doSomething(); doSomeInstancing.prop = ; console. ( doSomeInstancing ); function doSomething () "bar" // add a property onto the prototype new "some value" // add a property onto the object log This results in an output similar to the following: { prop: , __proto__: { foo: , constructor: ƒ doSomething(), __proto__: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } } } "some value" "bar" As seen above, the of is . But, what does this do? When you access a property of , the browser first looks to see if has that property. __proto__ doSomeInstancing doSomething.prototype doSomeInstancing doSomeInstancing If does not have the property, then the browser looks for the property in the of (a.k.a. doSomething.prototype). If the of doSomeInstancing has the property being looked for, then that property on the of doSomeInstancing is used. doSomeInstancing __proto__ doSomeInstancing __proto__ __proto__ Otherwise, if the of doSomeInstancing does not have the property, then the of the __proto__ of doSomeInstancing is checked for the property. By default, the of any function's prototype property is . So, the of the of doSomeInstancing (a.k.a. the of doSomething.prototype (a.k.a. )) is then looked through for the property being searched for. __proto__ __proto__ __proto__ window.Object.prototype __proto__ __proto__ __proto__ Object.prototype If the property is not found in the of the of doSomeInstancing, then the of the of the of doSomeInstancing is looked through. However, there is a problem: the of the of the of doSomeInstancing does not exist. Then, and only then, after the entire prototype chain of 's is looked through, and there are no more s does the browser assert that the property does not exist and conclude that the value at the property is undefined. __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ Let's try entering some more code into the console: {} doSomething.prototype.foo = ; doSomeInstancing = doSomething(); doSomeInstancing.prop = ; .log( + doSomeInstancing.prop); .log( + doSomeInstancing.foo); .log( + doSomething.prop); .log( + doSomething.foo); .log( + doSomething.prototype.prop); .log( + doSomething.prototype.foo); ( ) function doSomething "bar" var new "some value" console "doSomeInstancing.prop: " console "doSomeInstancing.foo: " console "doSomething.prop: " console "doSomething.foo: " console "doSomething.prototype.prop: " console "doSomething.prototype.foo: " This results in the following: doSomeInstancing.prop: some value doSomeInstancing.foo: bar doSomething.prop: undefined doSomething.foo: undefined doSomething.prototype.prop: undefined doSomething.prototype.foo: bar Different ways to create objects and the resulting prototype chain Objects created with syntax constructs var o = {a: }; var b = [ , , ]; { ; } 1 // The newly created object o has Object.prototype as its [[Prototype]] // o has no own property named 'hasOwnProperty' // hasOwnProperty is an own property of Object.prototype. // So o inherits hasOwnProperty from Object.prototype // Object.prototype has null as its prototype. // o ---> Object.prototype ---> null 'yo' 'whadup' '?' // Arrays inherit from Array.prototype // (which has methods indexOf, forEach, etc.) // The prototype chain looks like: // b ---> Array.prototype ---> Object.prototype ---> null function f () return 2 // Functions inherit from Function.prototype // (which has methods call, bind, etc.) // f ---> Function.prototype ---> Object.prototype ---> null A "constructor" in JavaScript is "just" a function that happens to be called with the . With a constructor new operator { .vertices = []; .edges = []; } Graph.prototype = { addVertex: function(v) { .vertices.push(v); } }; var g = Graph(); function Graph () this this this new // g is an object with own properties 'vertices' and 'edges'. // g.[[Prototype]] is the value of Graph.prototype when new Graph() is executed. ECMAScript 5 introduced a new method: . Calling this method creates a new object. The prototype of this object is the first argument of the function: With Object.create Object.create() var a = {a: }; var b = Object.create(a); console. (b.a); var c = Object.create(b); var d = Object.create(null); console. (d.hasOwnProperty); 1 // a ---> Object.prototype ---> null // b ---> a ---> Object.prototype ---> null log // 1 (inherited) // c ---> b ---> a ---> Object.prototype ---> null // d ---> null log // undefined, because d doesn't inherit from Object.prototype Using of another object demonstrates prototypical inheritance with the operation: delete Operator with Object.create and new operator Object.create delete var a = {a: }; var b = Object.create(a); console. (a.a); console. (b.a); b.a= ; console. (a.a); console. (b.a); b.a; console. (a.a); console. (b.a); a.a; console. (a.a); console. (b.a); 1 log // print 1 log // print 1 5 log // print 1 log // print 5 delete log // print 1 log // print 1(b.a value 5 is deleted but it showing value from its prototype chain) delete log // print undefined log // print undefined The operator has a shorter chain in this example: new { .vertices = [ , ]; } var g = Graph(); console. (g.vertices); g.vertices = ; console. (g.vertices); g.vertices; console. (g.vertices); function Graph () this 4 4 new log // print [4,4] 25 log // print 25 delete log // print undefined ECMAScript 2015 introduced a new set of keywords implementing . The new keywords include , , , , and . With the class keyword classes class constructor static extends super ; constructor(height, width) { .height = height; .width = width; } } constructor(sideLength) { super(sideLength, sideLength); } { .height * .width; } { .height = newLength; .width = newLength; } } var square = Square( ); 'use strict' { class Polygon this this { class Square extends Polygon get area () return this this set sideLength (newLength) this this new 2 The lookup time for properties that are high up on the prototype chain can have a negative impact on the performance, and this may be significant in the code where performance is critical. Additionally, trying to access nonexistent properties will always traverse the full prototype chain. Performance Also, when iterating over the properties of an object, enumerable property that is on the prototype chain will be enumerated. To check whether an object has a property defined on and not somewhere on its prototype chain, it is necessary to use the method which all objects inherit from . To give you a concrete example, let's take the above graph example code to illustrate it: every itself hasOwnProperty Object.prototype console. (g.hasOwnProperty( )); console. (g.hasOwnProperty( )); console. (g.hasOwnProperty( )); console. (g.__proto__.hasOwnProperty( )); log 'vertices' // true log 'nope' // false log 'addVertex' // false log 'addVertex' // true is the only thing in JavaScript which deals with properties and does traverse the prototype chain. hasOwnProperty not Note: It is enough to check whether a property is . The property might very well exist, but its value just happens to be set to . not undefined undefined One misfeature that is often used is to extend or one of the other built-in prototypes. Bad practice: Extension of native prototypes Object.prototype This technique is called monkey patching and breaks . While used by popular frameworks such as Prototype.js, there is still no good reason for cluttering built-in types with additional functionality. encapsulation non-standard The good reason for extending a built-in prototype is to backport the features of newer JavaScript engines, like . only Array.forEach Here are all 4 ways and their pros/cons. All of the examples listed below create exactly the same resulting object (thus logging the same results to the console), except in different ways for the purpose of illustration. Summary of methods for extending the prototype chain inst and prototype Object.getPrototypeOf JavaScript is a bit confusing for developers coming from Java or C++, as it's all dynamic, all runtime, and it has no classes at all. It's all just instances (objects). Even the "classes" we simulate are just a function object. You probably already noticed that our has a special property called prototype. This special property works with the JavaScript operator. The reference to the prototype object is copied to the internal property of the new instance. For example, when you do , JavaScript (after creating the object in memory and before running function with defined to it) sets function A new [[Prototype]] var a1 = new A() A() this a1. . When you then access properties of the instance, JavaScript first checks whether they exist on that object directly, and if not, it looks in . This means that all the stuff you define in is effectively shared by all instances, and you can even later change parts of and have the changes appear in all existing instances, if you wanted to. [[Prototype]] = A.prototype [[Prototype]] prototype prototype If, in the example above, you do then would actually refer to , var a1 = new A(); var a2 = new A(); a1.doSomething Object.getPrototypeOf(a1).doSomething which is the same as the you defined, i.e. . A.prototype.doSomething Object.getPrototypeOf(a1).doSomething == Object.getPrototypeOf(a2).doSomething == A.prototype.doSomething In short, is for types, while is the same for instances. prototype Object.getPrototypeOf() is looked at , i.e. , , etc., until it's found or returns null. [[Prototype]] recursively a1.doSomething Object.getPrototypeOf(a1).doSomething Object.getPrototypeOf(Object.getPrototypeOf(a1)).doSomething Object.getPrototypeOf So, when you call var o = Foo(); new JavaScript actually just does var o = Object(); o.[[Prototype]] = Foo.prototype; Foo.call(o); new (or something like that) and when you later do o.someProp; it checks whether has a property . If not, it checks , and if that doesn't exist it checks , and so on. o someProp Object.getPrototypeOf(o).someProp Object.getPrototypeOf(Object.getPrototypeOf(o)).someProp In conclusion It is essential to understand the prototypal inheritance model before writing complex code that makes use of it. Also, be aware of the length of the prototype chains in your code and break them up if necessary to avoid possible performance problems. Further, the native prototypes should be extended unless it is for the sake of compatibility with newer JavaScript features. never Credits Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain Published under license Open CC Attribution ShareAlike 3.0