Prototype Inheritance in Javascript
What is prototype chain and why exist?
Prototype Chain is the built-in mechanism that allows objects to inherit features (properties and methods) from other objects.
Main initial reason is to save the memory space. The inherent idea from OOP langrage(java specifically on those days) is very efficient and obvious way. Prototype chain is a lightweight and flexible method to achieve.
For Instance, If every single object or array you created had to store its own copies of all methods (like toString, valueOf, or array methods), it would consume a massive amount of memory.
Prototype

prototype
Foo.prototype.constructor === Foo; // true
f1.__proto__ === Foo.prototype; // true
f1.constructor === Foo; // true
f1 don’t have constructor, however depends on prototype chain engine will search f1.__proto__. This is line is equivalent to Foo.prototype.constructor === Foo
f1 instantiate a Foo:
f1.__proto__linkFoo.prototypef1have a constructor which isFoosinceFoo.prototypehave a constructor
Object.create()
Syntax is Object.create(proto[, propertiesObject])
var newObj = Object.create(obj);
newObj.__proto__ == obj; // true
new
When js running this line:
let person1 = new Person(...);new actually doing:
- Creates a blank, plain JavaScript object
person1 = {}; - Links (sets the constructor of) this object to another object;
person1.constructor is Person - Passes the newly created object from Step 1 as the this context;
this -> person1 - Returns this if the function doesn’t return an object.
Prototype Chain
This is object example. But Object is NOT we used here
Person = {
name: 'text',
age: 12,
};
const p1 = {};
p1.__proto__ = Person; // it is wrong
1
function Person(name, age) {
this.name = name;
this.age = age;
}
console.log(Person.prototype); // {} (empty obj)
console.log(Person.prototype.constructor === Person); // true
2
Just for understanding. This is NOT right way
function Person(name, age) {
this.name = name;
this.age = age;
}
const p1 = Object.create(Person);
console.log(p1.__proto__ === Person); // true
new instance should use function Prototype as chain
This is the right way
function Person(name, age) {
this.name = name;
this.age = age;
}
const p1 = Object.create(Person.prototype); // build chain
console.log(p1.__proto__ === Person.prototype); // true
also you could link manually
function Person(name, age) {
this.name = name;
this.age = age;
}
const p1 = {};
p1.__proto__ = Person.prototype; // link chain manually
p1.constructor('p1', 30);
console.log(p1.age);How to initialized
function Person(name, age) {
this.name = name;
this.age = age;
}
const p1 = Object.create(Person.prototype);
Person.apply(p1, ['p1', 31]);
const p2 = Object.create(Person.prototype);
p2.constructor('p2', 32);
console.log(p1); // Person { name: 'p1', age: 31 }
console.log(p2); // Person { name: 'p2', age: 32 }
If you want a instance function
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.print = function () {
console.log(this.name, this.age);
};
const p1 = Object.create(Person.prototype);
const p2 = Object.create(Person.prototype);
p1.constructor('p1', 31);
p2.constructor('p2', 32);
p1.print();
p2.print();Summary
const myNew = (constructor, ...args) => {
const newObj = Object.create(constructor.prototype);
const result = constructor.call(newObj, 'p1', 31);
return typeof result === 'object' ? result : newObj;
};
const p1 = (Person, 'p1', 31);
// equivalent to
const p1 = new Person('p1', 31);Person.prototype can be consider as a share level.
ES5 inheritance
function SuperType(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function () {
alert(this.name);
};
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
SubType.prototype = Object.create(SuperType.prototype, {
constructor: {
value: SubType,
enumerable: false,
writable: true,
configurable: true,
},
});
SubType.prototype.sayAge = function () {
alert(this.age);
};
let instance = new SubType('gim', '17');
instance.sayName(); // 'gim'
instance.sayAge(); // '17'
es5
ES6 inheritance
class SuperType {
constructor(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
sayName() {
alert(this.name);
}
}
class SubType extends SuperType {
constructor(name, age) {
super(name);
this.age = age;
}
sayAge() {
alert(this.age);
}
}
let instance = new SubType('gim', '17');
instance.sayName(); // 'gim'
instance.sayAge(); // '17'