写点什么

JavaScript 寄生式组合继承

作者:大熊G
  • 2022 年 6 月 09 日
  • 本文字数:1749 字

    阅读完需:约 6 分钟

JavaScript寄生式组合继承

组合继承

组合继承也被称为伪经典继承,它综合了我们昨天说的原型链和盗用构造函数,将俩者的有点结合在了一起。它的基本思想是使用原型链继承原型上的属性和方法,通过盗用构造函数继承实例属性,这样的好处就是可以把方法定义在原型上复用,每个实例又有自己的属性。


function SuperType (name) {        this.name = name;        this.colors = ["red","yellow","bule"];    }    SuperType.prototype.sayName = function(){        console.log(this.name)    }    function SubType(name,age){        SuperType.call(this,name);        this.age = age;    }    SubType.prototype = new SuperType();    SubType.prototype.sayAge = function(){        console.log(this.age);    }    let instancel = new SubType("jackson",22);    instancel.colors.push("pink");    instancel.sayName(); // "jackson"    instancel.sayAge();//22    console.log(instancel.colors);// ["red", "yellow", "bule", "pink"]        let instance2 = new SubType("bear", 20);    console.log(instance2.colors); // ["red", "yellow", "bule"]    instance2.sayName(); // "bear";    instance2.sayAge(); // 20

复制代码


上面的代码大家有没有一种豁然开朗的感觉,SubType 调用 SuperType,并且传入 name,然后定义自己的属性 age,此外 SubType.prototype 也被赋值位 SuperType 实例。原型赋值后又在这个原型上添加 sayage 方法,这样创建俩个 subType 实例,这俩个实例都有自己属性,还可以共享相同的方法。


组合继承弥补了原型链和盗用构造函数的不足,是 js 中使用最多的继承模式。


寄生式继承

寄生式继承就是用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。

/ 寄生式继承    function subobject(obj) {        let clone = Object(obj);        clone.sayName = function(){            console.log("jackson")        };        return clone;    }    let sub = {        name:"bear"    }    let sup = subobject(sub);    sup.sayName();//jackson

复制代码

这个例子基于 sub 对象返回一个新对象,返回的 sup 对象有 sub 的属性和方法,还有一个新方法 sayName()。

寄生式继承同样适合主要关注对象,而不在乎类型和构造函数的场景。object()函数不是寄生式继承所必需的,任何返回新对象的函数都可以在这里使用。

注意 通过寄生式继承给对象添加函数会导致函数难以重用,与构造函数模式类似。


寄生式组合继承

组合继承存在这一定的效率问题,它的父类构造函数始终会被调用俩次,一次在创建字类原型时调用,另一次在子类构造函数中调用。本质上子类只需要在执行时重写自己的原型就行了。

  function inheritPrototype(subType, superType) {        let prototype = Object(superType.prototype); // 创建对象        prototype.constructor = subType; // 增强对象        subType.prototype = prototype; // 赋值对象    }

复制代码

这个 inheritPrototype()函数实现了寄生式组合继承的核心逻辑。这个函数接收两个参数:子类构造函数和父类构造函数。在这个函数内部,第一步是创建父类原型的一个副本。然后,给返回的 prototype 对象设置 constructor 属性,解决由于重写原型导致默认 constructor 丢失的问题。最后将新创建的对象赋值给子类型的原型。如下例所示,调用 inheritPrototype()就可以实现前面例子中的子类型原型赋值:

function SuperType(name) {        this.name = name;        this.colors = ["red", "blue", "green"];    }    SuperType.prototype.sayName = function () {        console.log(this.name);    };
function SubType(name, age) { SuperType.call(this, name); this.age = age; } inheritPrototype(SubType, SuperType); SubType.prototype.sayAge = function () { console.log(this.age); };
复制代码

这里只调用了一次 SuperType 构造函数,避免了 SubType.prototype 上不必要也用不到的属性, 因此可以说这个例子的效率更高。而且原型链仍然保持不变。

寄生式组合继承可以算是引用类型继承的最佳模式。

发布于: 刚刚阅读数: 3
用户头像

大熊G

关注

每天都在写bug的硬核男人 2022.06.02 加入

前端

评论

发布
暂无评论
JavaScript寄生式组合继承_JavaScript_大熊G_InfoQ写作社区