组合继承
原理:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const Person = function (name, age) { this.name = name; this.age = age; }; Person.prototype.sayName = function () { console.log(this.name); };
const Male = function (name, age) { Person.call(this, name, age); this.gender = 'male'; };
Male.prototype = new Person();
Male.prototype.constructor = Male;
const p1 = new Male('whh', 23); console.log(p1);
|
图解
弊端:调用了两次父类的构造函数,导致原型中产生了无效的属性。
寄生组合式继承
原理:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。主要就是用一个空的构造函数,来当做桥梁,并且把其原型对象指向父构造函数的原型对象,并且实例化一个 temp,temp 会沿着这个原型链,去找到父构造函数的原型对象。举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| const Person = function (name, age) { this.name = name; this.age = age; }; Person.prototype.sayName = function () { console.log(this.name); };
const Male = function (name, age) { Person.call(this, name, age); this.gender = 'male'; };
const extend = function (subType, superType) { const Temp = function () {}; Temp.prototype = superType.prototype; let temp = new Temp(); subType.prototype = temp; temp.constructor = subType; };
extend(Male, Person);
const p1 = new Male('whh', 23); console.log(p1);
|
图解
这个例子的高效率体现在它只调用了一次 SuperType 构造函数,并且因此避免了在 SubType.prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用instanceof 和 isPrototypeOf()。
目前程序猿认为解决继承问题最好的方案
其他继承方式(不完美的)
参考: 掘金地址
原型式继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| // 原型式继承 function createObjWithObj(obj){ // * 传入一个原型对象 function Temp(){} Temp.prototype = obj let o = new Temp() return o }
// * 把Person的原型对象当做temp的原型对象 let temp = createObjWithObj(Person.prototype)
// * 也可以使用Object.create实现 // * 把Person的原型对象当做temp2的原型对象 let temp2 = Object.create(Person.prototype)
|
寄生式继承
1 2 3 4 5 6 7 8 9
| // 寄生式继承 // 我们在原型式的基础上,希望给这个对象新增一些属性方法 // 那么我们在原型式的基础上扩展 function createNewObjWithObj(obj) { let o = createObjWithObj(obj) o.name = "whh" o.age = 23 return o }
|
拷贝继承
1 2 3 4 5 6 7
| const extend2(Child, Parent) { let p = Parent.prototype let c = Child.prototype for (var i in p) { c[i] = p[i] } }
|
这个函数的作用,就是将父对象的 prototype 对象中的属性,一一拷贝给 Child 对象的 prototype 对象。使用的时候,这样写:
1 2 3
| extend2(Male, Person); let p1 = new Male('whh', 23); console.log(p1.age);
|