一、原型链继承
function a() { this.speack = function () { console.log('第一个元素'); } } function b() { this.ask = function () { console.log('第二个元素'); } } b.prototype = new a(); b.prototype.constructor = b; //b的prototype的constructor重新改写为它自身 let c = new b(); c.speack();
定义:构造函数在创建实例前,将它的原型设置为另一个构造函数的实例,这样创建的实例可以通过原型链继承属性和方法,称为原型链继承。
特点:1、构造函数可以继承父元素的属性和方法,但是构造函数只有一个prototype,所以只能单继承,不能多继承。
2、构造函数的原型上的属性在继承的实例上改变时,其他实例上的原型属性也会改变。
特点2代码解释:
function a() { this.speack = function () { console.log('第一个元素'); } this.arr=[1,2,3] } function b() { this.ask = function () { console.log('第二个元素'); } } b.prototype = new a(); b.prototype.constructor = b; let c = new b(); let d = new b(); c.arr.push(4); console.log(c.arr); console.log(d.arr);
可以看见c实例改变arr属性,d实例上的arr属性也改变,可以这样理解,c、d都是b的实例,c、d查找arr属性时,通过__proto__查找到b的prototype,然后c修改b的prototype中的arr属性,当打印d的arr属性时,d会查找__proto__找到b的prototype,找到的是c修改的arr属性,所以c、d的arr属性是一致的,这就是原型链继承的缺陷。
二、借用构造继承
function a1() { this.speack = function () { console.log('第一个元素'); } } function b1() { a1.call(this, '借用构造继承'); } let c1 = new b1(); c1.speack();
定义:构造函数内部使用call/apply/bind,执行另一个函数,将这个函数的属性和方法通过this赋值给构造函数,称为借用构造继承。可以使用apply、bind、call继承多个。
特点:1、借用构造继承可以向构造函数传参数。
2、借用构造继承只能继承函数中的属性,不能继承函数原型中的属性,所以不能实现复用。
3、可以实现多继承。
三、组合继承
function a2() { this.speack = function () { console.log('第一个元素') } } function b2() { a2.call(this); } b2.prototype = new a2(); b2.prototype.constructor = b2; let c2 = new b2(); c2.speack();
定义:函数将原型链继承和借用构造继承组合在一起。
特点:1、可以继承构造函数的属性和原型,并且一个实例修改继承属性后,不会影响其他的实例。
2、可以继承原型,所以能实现函数的复用。
四、原型式继承
function a3(obj) { let fn = function () { } fn.prototype = obj; return new fn(); } function b3() { } let c3 = new b3(); let d3 = a3(c3);
特点:1、跟原型链继承缺陷一样,其中一个实例修改原型上的属性,其它实例上的原型属性也会改变,也就是原型共享。
五、寄生式继承
function a4(obj) { let fn = function () { } fn.prototype = obj; return new fn(); } function b4() { } function c4(arg) { let obj = a4(arg); obj.name = 'custom'; return obj } let d4 = new b4(); let e4 = c4(d4); console.log(e4.name)
特点:1、跟原型链继承缺陷一样,其中一个实例修改原型上的属性,其它实例上的原型属性也会改变,也就是原型共享。
2、可以在构造函数上添加自定义属性。
六、寄生组合继承
function a5(arg) { let obj = function () { } obj.prototype = arg; return obj } function b5() { } const c5 = a5(b5.prototype) function d5() { b5.call(this) } d5.prototype = c5; d5.prototype.constructor = d5; let e5 = new d5(); console.log(e5.name)
特点:1、修复原型共享带来的问题。
2、可以实现参数的复用。