Javascript inheritance behind the scene __proto__, [[prototype]] and prototype
The prototype is a property on a constructor function that sets what will become the __proto__ property on the constructed object.
The key to understanding inheritance in Javascript is to understanding how a Javascript Egg laying process by the parent hen; Javascript inheritance happens in prototype inherited but classical class technically and conceptually is not existed.
This is a note about clearing up the confusion of prototype, __proto__ and inheritance in Javascript. Most of the content here is collected from the two very great articles by Dmitry Soshnikov and Kenneth Kin Lum : http://dmitrysoshnikov.com/ecmascript/javascript-the-core/
https://kenneth-kin-lum.blogspot.tw/2012/10/javascripts-pseudo-classical.html?showComment=1484288337339#c1393503225616140233
Example 0 : [[prototype]] vs __proto__ vs prototype
speakingjs.com and javascripttutorial.com are the best resource which explains the relation of [[prototype]], __proto__ and prototype from the basic to application, also very important that they visualize the relation in graphic.
Every object can have another object as its prototype. Then the former object inherits all of its prototype’s properties. An object specifies its prototype via the internal property
[[Prototype]]
. The chain of objects connected by the[[Prototype]]
property is called the prototype chain:
To see how prototype-based (or prototypal) inheritance works, let’s look at an example (with invented syntax for specifying the
[[Prototype]]
property):
var proto = {
describe: function () {
return 'name: '+this.name;
}
};
var obj = {
[[Prototype]]: proto,
name: 'obj'
};> obj.describe
[Function]> obj.describe()
'name: obj'
The
__proto__
is an accessor property of theObject.prototype
object. It exposes the internal prototype linkage ([[Prototype]])
of an object through which it is accessed (by javascripttutorial).
function Foo(name) {
this.name = name;
}var b = new Foo('b');
var a = new Foo('a');
b.say = function() {
console.log('Hi from ' + this.whoAmI());
}console.log(a.__proto__ === Foo.prototype); // true
console.log(a.__proto__ === b.__proto__); // true
JavaScript engine adds the
say()
method to theb
object, not theFoo.prototype
object.As you see in the diagram, the
a.__proto__
exposes the[[Prototype]]
that points to theFoo.prototype
object. Similarly,b.__proto__
also points to the same object asa.__proto__:
Example 1 : creating object by constructor
This is a example from Dmitry, about creating objects by constructor, it is going to show how an prototype and __proto__ works in inheritance mechanism.
Besides creation of objects by specified pattern, a constructor function does another useful thing — it automatically sets a prototype object for newly created objects. This prototype object is stored in the
ConstructorFunction.prototype
property.E.g., we may rewrite previous example with
b
object using a constructor function. Thus, the role of the objecta
(a prototype)Foo.prototype
plays:
Create Foo object with prototype x and calculate()
function Foo(y) {
this.y = y;
}Foo.prototype.x = 10;
Foo.prototype.calculate = function (z) {
return this.x + this.y + z;
};
Create instance b using the object Foo:
var b = new Foo(20);b.calculate(30); // 60console.log(
b.__proto__ === Foo.prototype, // true
b.__proto__.calculate === Foo.prototype.calculate // true
b.__proto__.calculate === b.calculate, // true
Foo === b.constructor, // true
Foo === Foo.prototype.constructor, // true
);
As it is showed above, b is inherited the methods from Foo(). “Foo.prototype” automatically creates a special property “constructor”, which is a reference to the constructor function itself.
Instances “b” may found it via delegation and use to check their constructor.
Example 2 : JavaScript Classical Inheritance diagram
This is an example from Kenneth, also about creating object by constructor but we are focus on the issue of prototype chain during those series of objects and instances. Prototype objects are also just simple objects and may have their own prototypes. If a prototype has a non-null reference to its prototype, and so on, this is called the prototype chain (by Dmitry).
The following is a chart of JavaScript Pseudo Classical Inheritance. The constructor Foo is just a class name for an imaginary class. The foo object is an instance of Foo.
And now we can see from the diagram why when we inherit Dog from Animal, we would do:
function Dog() {} // the usual constructor function
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
What happens when new( ) an instance:
Note that the prototype in Foo.prototype is not to form a prototype chain. Foo.prototype points to some where in a prototype chain, but this prototype property of Foo is not to form the prototype chain. What constitute a prototype chain are the __proto__ pointing up the chain, and the objects pointed to by __proto__, such as going from foo.__proto__, going up to foo.__proto__.__proto__, and so forth, until null is reached.
Relation of __proto__ and prototype
JavaScript’s Pseudo Classical Inheritance works like this way: I am a constructor, and I am just a function, and I hold a prototype reference, and whenever foo = new Foo() is called, I will let foo.__proto__ point to my prototype object. So Foo.prototype and obj.__proto__ are two different concepts. Foo.prototype indicates that, when an object of Foois created, this is the point where the prototype chain of the new object should point to — that is, foo.__proto__ should point to where Foo.prototype is pointing at.
What if a function is needed to add
If woofie the object doesn’t have the move method, it will go up the prototype chain, just like any prototypal inheritance scenario, first to the object pointed to by woofie.__proto__, which is the same as the object that Dog.prototype refers to. If the method move is not a property of that object (meaning that the Dog class doesn’t have a method move), go up one level in the prototype chain, which is woofie.__proto__.__proto__, or the same as Animal.prototype.
Animal.prototype.move = function() { ... };
Even though foo.constructor === Foo, the constructor property is not foo’s own property. It is actually obtained by going up the prototype chain, to where foo.__proto__ is pointing at. The same is for Function.constructor. The diagram can be complicated, and sometimes confusing when we see Constructor.prototype, foo.__proto__, Foo.prototype.constructor.
To verify the diagram, note that even though foo.constructor will show a value, the property constructor is not foo’s own property, but is obtained by following up the prototype chain, as foo.hasOwnProperty(“constructor”) can tell.
Notes:
[[Prototype]]
An object specifies its prototype via the internal property
__proto__
brings direct access to [[Prototype]]
to the language(by speakingjs.com).
prototype
is the object that is used to build __proto__
when you create an object with new.
prototype
is not available on the instances themselves (or other objects), but only on the constructor functions.
prototype
is only available on functions since they are copied from Function
and Object,
but in anything else it is not. However, __proto__
is available everywhere.
( new Foo ).__proto__ === Foo.prototype //true
( new Foo ).prototype === undefined //true
delegate prototypes and concatenative inheritance
Cat.prototype = new Animal();
//it will properly follow the prototype chain through the inheritance hierarchy.Cat.prototype = Animal.prototype
//any runtime changes to the Cat prototype would also affect the Animal
static properties/functions do not exist on the prototype. The prototype
is only used when a new
instance is created.
Like this story? It is helpful to others? It helps me know if you’d like to see write more about his topic and helps people see the story, when tap the heart below.
Reference:
http://speakingjs.com/es5/index.html
http://www.javascripttutorial.net/javascript-prototype/
http://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript
http://dmitrysoshnikov.com/ecmascript/javascript-the-core/
https://www.quora.com/What-is-the-difference-between-__proto__-and-prototype
http://www.jisaacks.com/prototype-vs-proto/
http://kenneth-kin-lum.blogspot.tw/2012/10/javascripts-pseudo-classical.html
Hacker Noon is how hackers start their afternoons. We’re a part of the @AMI family. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!