js继承详解

一、原型链继承

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、可以实现参数的复用。

原文地址:https://www.cnblogs.com/uimeigui/p/14439948.html