Prototype chain inheritance
The most common inheritance methods involve constructors, prototypes, and instances
- Each constructor has a prototype object
- The prototype object also contains a pointer to the constructor
The instance contains a pointer to the prototype object
There are problems with this inheritancefunction Parent(){ this.name="parent" this.own = [1,2,3] } function Child(){ this.type ="child" } Child.prototype = new Parent() console.log(new Child()) // Parent { type: 'child' } let c1 = new Child(); let c2 = new Child(); c1.own.push(4) console.log(c1.own,c2.own) // [ 1, 2, 3, 4 ] [ 1, 2, 3, 4 ]
Because the two instances use the same prototype object and share memory space, when one changes, the other also changes
Constructor inheritance
call implementation
function Parent(){ this.name="parent" this.own = [1,2,3] } Parent.prototype.getName = function () { return this.name; } function Child(){ Parent.call(this) this.type ="child" } const child = new Child() console.log(child) // Child { name: 'parent', own: [ 1, 2, 3 ], type: 'child' } console.log(child.getName()) // child.getName is not a function
This method solves the disadvantages of prototype shared memory, which also brings new problems. Only instance properties and methods of the parent class can be inherited, and prototype properties or methods cannot be inherited.
Combinatorial inheritance
This method combines the advantages and disadvantages of the first two inheritance methods and combines inheritance
function Parent(){ this.name="parent" this.own = [1,2,3] } Parent.prototype.getName = function () { return this.name; } function Child(){ // Second call Parent.call(this) this.type ="child" } // Calling Parent3() for the first time Child.prototype = new Parent() // Manually hang up the constructor and point to its own constructor Child.prototype.constructor = Child; let c1 = new Child() let c2 = new Child() c1.own.push(4) console.log(c1.own,c2.own) // [ 1, 2, 3, 4 ] [ 1, 2, 3 ] console.log(c1.getName()) // parent console.log(c2.getName()) // parent
The Parent is executed twice. The first time is to change the Child's prototype, and the second time is to call the Parent through the call method. If the Parent is constructed once more, it will incur an additional performance overhead
Prototype inheritance
Use the object in ES5 Create method, which receives two parameters: one is the object used as the prototype of the new object, and the other is the object that defines additional properties for the new object (optional parameters)
let parent = { name:"parent", friend:['1',',2','3'], getName:function(){ return this.name } } let p1 = Object.create(parent) p1.name ="jake" p1.friend.push("a") let p2 = Object.create(parent) p1.friend.push("b") console.log(p1.name) // jake console.log(p1.name === p1.getName()) // true console.log(p2.name) // parent console.log(p1.friend) // [ '1', ',2', '3', 'a', 'b' ] console.log(p2.friend) // [ '1', ',2', '3', 'a', 'b' ]
The disadvantages of this inheritance method are obvious. The reference type properties of multiple instances point to the same memory, which may be tampered with
Parasitic inheritance
Prototype inheritance can obtain a shallow copy of the target object, and then enhance the ability of this shallow copy and add some methods. This inheritance method is called parasitic inheritance
The advantages and disadvantages are the same as prototype inheritance, but for the inheritance of ordinary objects, parasitic inheritance adds more methods on the basis of parent class than prototype inheritance
let parent = { name:"parent", friend:['1',',2','3'], getName:function(){ return this.name } } function clone(src) { let clone = Object.create(src); clone.getFriends = function() { return this.friend; }; return clone; } let p1 =clone(parent) console.log(p1.getName()) // parent console.log(p1.getFriends()) // [ '1', ',2', '3' ]
The method of getFriends is added, so that p1, an ordinary object, adds another method in the inheritance process. It still calls the constructor of the parent class twice, resulting in waste
Parasitic combinatorial inheritance
Solve the shortcomings of the previous inheritance methods, better achieve the desired results of inheritance, reduce the construction times and reduce the performance overhead
function clone(parent, child) { // Use object instead Create can reduce the process of one more construction in composite inheritance child.prototype = Object.create(parent.prototype) child.prototype.constructor = child; } function Parent() { this.name = "parent" this.friend = ['1', ',2', '3'] } Parent.prototype.getName = function () { return this.name } function Child() { Parent.call(this) this.friend = "labor" } clone(Parent, Child) Child.prototype.getFriends = function(){ return this.friend } let c1 = new Child() console.log(c1) // Child { name: 'parent', friend: 'labor' } console.log(c1.getName()) // parent console.log(c1.getFriends()) // labor
Extensions in ES6 also adopts this method
classification
Do not use object The method of create is constructor inheritance and prototype chain inheritance. They are combined into composite inheritance
Use object The method of create is prototype inheritance and parasitic inheritance. Based on this, there is parasitic composite inheritance, which is similar to ES6 extensions