Before we begin digging into what how [[Prototype]]
inheritance works and what it entails, let us understand one interesting fact about JavaScript:
If you have seen a code written in ES6 or even React, you are most likely to have come across the ES6 class
along with class-based terms like super()
instanceOf()
, and constructor()
. This may mislead you into thinking that JavaScript is traditionally a class-oriented language, which isn’t true.
Class Definition
In traditional class-oriented languages, a class acts as a blueprint. When you instantiate a class, the class is actually copied into its instance (object). The same behaviour occurs when a subclass extends a superclass. This behavior is analogous to the building plan in the blueprint of a house being copied to build an actual house.
When you make a constructor call with the new
keyword, a copy operation occurs.
But with JavaScript, this is not the case. There is no class. What we have is an ordinary function being used to ‘construct’ an object.
function ordinaryFunction () {
console.log('I am not a class, just an ordinary function');
}
const ords = new ordinaryFunction();
Most importantly, a ‘copy operation’ does not occur. Instead, a new object is created. This new object is linked to the prototype object, which brings to the main question.
WHAT IS A PROTOTYPE OBJECT?
The [[Prototype]]
mechanism is a mechanism which links objects to other objects in some kind of chain, the prototypal chain. This behaviour underpins the whole nature of JavaScript.
function Foo() {
// ...
}
var b = new Foo();
Object.getPrototypeOf( b ) === Foo.prototype; // true
The getPrototype()
static method checks for the prototype object of b
. Here, it indicates that object (b) is actually linked to the foo.prototype
object.
To be thorough, whenever a constructor call (new...
) is made, an object is created. That newly created object will link to an object with is referenced to by the fn.prototype
property, which incidentally is the prototype object of that chain.
NOTE: In
fn.prototype
, thefn
is just any function used to make the call. In our case it wasFoo
. It could also beCalculateHeight
,SuccessMessage
or any other simple function in your JavaScript.
In other words, when the new
call is made, the newly created object b
will get an internal [[Prototype]]
link to the object which Foo.prototype
is pointing at.
function Foo() {
// ...
}
Foo.prototype; // { }
What does this link do?
If you know of true class-oriented languages, you know that in class inheritance a copy of the class is used to construct an object. However, with prototypal inheritance of JavaScript, a link is created through which objects on the top of the chain can delegate access of its properties and methods to objects lower on the chain:
The Fn.prototype
Object (aka Prototype Object)
Here’s something interesting to know. The fn.prototype
object has a couple of in-built properties in it, one of them is the ‘constructor’ property.
function Baz() {
// ...
}
Baz.prototype.constructor === Baz; // true
// Here, the constructor property references the function the prototype object is linked to.
var b = new Baz();
b.constructor === Baz; // true
The object b
is created from the constructor call with Baz
function. This begs the question: How is it able to get access to the constructor
property even though such property was never directly defined in the object? The answer? It is via [[Prototype]]
delegation.
All object prototypes (like baz.prototype
) comes with an in-built constructor
property. Thus, thanks to prototypal inheritance, any other objects linked to that prototype object (via new
construcutor call) will automatically have access to that property along with the following other in-built properties:
hasOwnProperty()
isPrototypeOf()
propertyIsEnumerable()
toString()
toLocaleString()
hasOwnProperty()
valueOf()
It is however important to note that the in-built prototype object can be overridden:
function Bar() { /* .. */ }
Bar.prototype.constructor = // Bar
Bar.prototype = { /* .. */ }; // overrides the on-built object, assigns a new prototype object
var boo = new Bar();
boo.constructor === Bar; // false!
boo.constructor === Object; // true!
To illustrate how prototypal inheritance truly works, lets consider the following example
function Foo(title) {
this.title= title;
}
Foo.prototype.myTitle = function() {
return this.title;
};
var a = new Foo( "king" );
var b = new Foo( "queen" );
a.myTitle(); // "king"
b.myTitle(); // "queen"
Two separate objects are created, a
and b
. Here are two important points which essentially summarizes how prototypal inheritance (object delegation) works:
When both objects were created with
new
, a parameter was passed in to the constructor function (Foo). This parameter is then stored into both instance objects as thetitle
property (withthis
referring to the context objects).You may not be surprised to find the
myTitle()
method call working despite the fact that the method was never defined and is not present in eithera
orb
. If you are surprised, then this is why:
Foo.prototype.myTitle = function() {
return this.title;
};
The myTitle()
method was passed as a method into the foo.protoype
object, which is the highest on the prototypal chain
. So even when both a
and b
didn’t have the myTitle
method present in each of them, they both had access to the prototype object because they are linked to it. So all they had to do was climb up and access it from there.
This is basically all you need to know about the [[Protoype]]
mechanism in JavaScript. It enables objects link and delegate access to each other in a form of chain. That way, objects lower on the chain can have access to properties and methods in objects higher on the chain.
We’ll leave that for our next episode of the Explain like I’m 5 series.
YOU MAY ALSO LIKE:
P/S: If you like articles like this follow this blog to never miss an update. If you are learning JavaScript, you’ll definitely want to check out my JavaScript Notes.
Top comments (3)
Great job Kingsley!
Thank you.
Glad you liked it!
It can be a complicated topic. You did great. Although there is a lot more stuff around this. Hope you cover that too later on.