JavaScript is fun: Object Prototypes, Prototype Chain and Inheritance
A beginner-friendly introduction on Javascript prototype, prototype-chain & inheritance.
)}
Table of Content
Prototype-based Language
According to MDN document: *JavaScript is often described as a prototype-based language — to provide inheritance, objects can have a prototype object, which acts as a template object that it inherits methods and properties from.*
In other words, prototypal inheritance is a form of object0oriented code reuse. Javascript is one of the only [mainstream] object-oriented languages to use prototypal inheritance. Almost all other object-oriented languages are classical.
Understandd Protoype
- In Javascript, every function (with the exception of *arror function) has a special property
prototype
. Every time you create a function, thisprototype
becomes the property of that function, which is by default an empty object. -
every object has a hidden property
__proto__
, this property is linking to an object from which this object inherits properties from.* Either use
.__proto__
or useObject.getPrototypeOf
will give you the exactly same object. __proto__
is a property that only exists on objects,prototype
on the other hand is a property that only exists on objects.-
__proto__
of an object is the value of theprototype
property of the constructor function from which that object is created.Let’s see an example with the code for a better visualizaion:
function Person(name) { name: this.name } var boy = new Person('Oliver'); console.log(Person.prototype === boy.__proto__); // true
-
In an object, if that property is pointing to an object then the engin will treat this object’s properties as if they were on the instance itself. In other words, every object can link to another object via
__proto__
property and access it’s properties like they were it’s own.function Person(name) { name: this.name } Person.prototype.sayHi = function() { console.log("Hi"); } var boy = new Person('Oliver'); boy.sayHi();
* Object
boy
doesn’t have methodsayHi()
, so the engine will search methodsayHi()
in its__proto__
, that isPerson.prototype
(rememberboy.__proto__ === Person.prototype
). -
A property value or method is searched in a current object first. If it’s not found, the search continue in the *prototype chain until the property is found or prototype chain ends.
var obj1 = {a: 1}; var obj2 = Object.create(obj1); obj2.hasOwnProperty('a'); // false obj2.a; // 1 obj2.a = 2; obj2.hasOwnProperty('a'); // true obj2.a; // 2 obj2.__proto__.a; // 1
Prototype Chain
As memetioned above, the sequence of objects traversed in the object manner form a singly linked list known as the “prototype chain” of the inital obejct.
Prototype chain terminates with null
var obj = {};
obj.__proto__.__proto___ // null
Inheritance
Constructor-Based Inheritance
function Parent ( name ) {
this.name = name
this.friends = ["Shannon", "Jeremy"]
}
Parent.prototype.getName = function () {
console.log(this.name)
}
function Child (name) {
Parent.call(this, name);
}
Child.prototype = new Parent();
Child.prototype.constructor = Child
var child1 = new Child('Oli');
child1.friends.push("Liz");
var child2 = new Child("Liz");
child1.getName(); // Oli
console.log(child1.friends); // [ 'Shannon', 'Jeremy', 'Liz' ]
child2.getName(); // Liz
console.log(child2.friends); // [ 'Shannon', 'Jeremy' ]
Using constructor functions with the new
keyword is a handy way to create objects, but it can cause problems by obscuring, and sometimes interfering with, the benefits of using JavaScript in a purely prototypal way. This is most obvious when we try to inherit from another object and take advantage of the delegation features in the prototype system.
Prototypal Inheritance
function Parent (name) {
this.name = name
}
Parent.prototype.getName = function () {
return this.name;
}
function Child (name, age){
Parent.call(this, name);
this.age = age;
}
function inheritPrototype (Child, Parent) {
var prototype = Object.create(Parent.prototype);
prototype.constructor = Child;
Child.prototype = prototype;
}
inheritPrototype(Child, Parent);
var myChild = new Child("Oli", 23);
console.log(myChild.getName(), myChild.age); // Oli 23
myChild
has access to both the Child.prototype
and Parent.prototype
(and automatically Object.prototype
, since Parent
is an object).
Since Parent.prototype
has the getName
function, we can access getName
on myChild
.
ES6 actually introduced an easier syntax for constructor functions and working with prototypes: classes!
ES6 Class extends
Classes are only *syntactical sugar` for constructor functions. Everything still works the same way.
class Car {
constructor(brand) {
this.carname = brand;
}
present() {
return 'I have a ' + this.carname;
}
}
class Model extends Car {
constructor(brand, mod) {
super(brand);
this.model = mod;
}
show() {
return this.present() + ', it is a ' + this.model;
}
}
var mycar = new Model("Ford", "Mustang");
console.log(mycar.show()); // I have a Ford, it is a Mustang
We write classes with class
keyword. A class has a constructor
function which is basically the constructor function we wrote in the ES5 syntax.
Another greate thing about classes, is that we can easily extend
other classes.
Summary
Hopefully, you now understand prototype and the use of prototype in the wonderful world of Javascript!