JS学习——js继承方式

一.原型链继承

原型链继承主要是通过修改原型中的prototype的指向,从而继承上级构造函数的公有属性

function Fn1 (name, age) {
    this.name = name;
    this.age = age;
}

    // Fn1扩展原型
Fn1.prototype.say = function () {
    alert('hello');
}

var father = new Fn1('大李', 30);

function Fn2 (name, age) {
    this.name = name;
    this.age = age;
}

两构造函数的结构图如下图


JS学习——js继承方式_第1张图片

现在需要Fn2创建的实例也能够使用say函数。但是,实例中的__proto__属性是不允许进行修改的,所以要想达到目的只有更改Fn2prototype的指向。目前有1,2两条可修改的线路,但是对于线路2,即Fn1.prototype = Fn2.prototype来说,存在缺陷:如果以后对Fn2prototype的任何修改都会同时修改Fn1的prototype,所以线路2不可行,选择线路1进行修改

JS学习——js继承方式_第2张图片

通过将上级函数的实例赋值给下级函数的原型,用来代替下级函数的原型,从而构造出原型链
Fn2.prototype = new Fn1();
以上就完成了原型链的搭建,但是为了原始结构的完整性,在Fn1的原型中修复constructor指向Fn2,即Fn2.prototype.constructor = Fn2

function Fn1 (name, age) {
    this.name = name;
    this.age = age;
}
// Fn1扩展原型
Fn1.prototype.say = function () {
    alert('hello');
}
var father = new Fn1('大李', 30);
function Fn2 (name, age) {
    this.name = name;
    his.age = age;
}
// 原型链构建
Fn2.prototype = new Fn1();
// constructor修复
Fn2.prototype.constructor = Fn2;
// Fn2扩展原型
Fn2.prototype.eat = function () {
    alert('fish');
}
var son = new Fn2('小李', 18);
console.log(son);
JS学习——js继承方式_第3张图片

二.组合方式继承

Fn1Fn2创建实例时都会创建相同的属性,如何让私有属性也能继承呢?改变Fn1this指针到Fn2就能解决问题
callapply改进原型链
callapply用法相似,相同点是第一个参数都是改变this指针到指定对象。不同点是call其余参数为对象的属性,如:Fn1.call(Fn2, name, age);apply只有两个参数,第二个参数为属性组成的数组,如:Fn1.call(Fn2, [name, age])

// 只需将原来的Fn2改为如下即可
function Fn2 (name, age) {
    Fn1.call(this, name, age);// this指的是Fn2
    // Fn1.apply(this, [name, age]);    
}

所有组合方式继承的本质就是结合callapply函数对原型链进行进一步完善
组合方式继承不仅仅只能继承上级,还能继承多个对象的私有属性

function Fn2 (name, age, height, weight) {
    Fn1.call(this, name, age);

    Fn3.call(this, height); 
    Fn4.call(this, weight); 
}

三.寄生方式继承

son的打印结果可以看出,虽然从上级全部继承,但是上级的原有私有属性也继承到了prototype里且为undefined,以寄生方式继承的目的就是为了出去上级继承的空属性
如何才能把从上级继承的为undefined的属性去掉了?如果我们从上级只继承公有属性该多好,如果能继承有公有属性但没有私有属性的对象呢?
寄生方式继承的主要思想就是用一个临时的空的过渡函数去获取上级函数的prototype,然后让下级函数继承这个空过渡函数

// 创建过渡函数
function Temp(){}
// 替换过渡函数原型
Temp.prototype = Fn1.prototype;
// 原型方式继承
Fn2.prototype = new Temp();

通过过渡替换的方法先让Temp的原型变为Fn1的原型,因为Temp没有私有属性,所有继承的Fn2不会携带多余属性

JS学习——js继承方式_第4张图片

你可能感兴趣的:(JS学习——js继承方式)