JavaScript 寄生式继承
1. 寄生式继承:类似于 原型式继承,实际上就是 原型式继承 + 工厂模式,直接上代码:
function object(o) { function F() {} F.prototype = o; return new F(); }
原型式继承 创建对象,用于被所有实例对象所共享,之后使用 工厂模式 给每个对象添加自身独有的属性:
function createAnother(original){ let clone = object(original); // 通过调用函数创建一个新对象 clone.sayHi = function() { // 以某种方式增强这个对象 console.log("hi"); }; return clone; // 返回这个对象 }
let person = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] }; let anotherPerson = createAnother(person); anotherPerson.sayHi(); // "hi"
个人感觉就是 原型式继承 给对象添加自身独有属性的操作部分挪到了一个函数【createAnother】内部,类似于 工厂模式,其他和 原型式继承 并无差异. 寄生式继承同样适合主要关注对象,而不在乎类型和构造函数的场景。
2. 寄生式组合继承:先用大白话解释一下,我们知道,在组合继承时,也就是 构造函数 + 原型链 方式,一方面在子构造函数中调用了父类构造函数,一方面又给子构造函数的原型 new了父构造函数,相当于两次调用父类构造函数。前者是我们所需要的步骤,即让父类构造函数属性成为子类实例属性不被共享,而后者会导致父类的属性在子类构造函数原型上,被所有对象所共享,这是我们不需要的。
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); // 第二次调用 SuperType() this.age = age; } SubType.prototype = new SuperType(); // 第一次调用 SuperType() SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function() { console.log(this.age); };
那么寄生式组合继承解决的就是这个问题,它采用某种方式,不再让子构造函数的原型去拥有父构造函数的实例属性,寄生式组合继承的基本模式如下所示:
function inheritPrototype(subType, superType) { let prototype = object.create(superType.prototype); // 创建对象 prototype.constructor = subType; // 增强对象 subType.prototype = prototype; // 赋值对象 }
现在再和二次调用父类构造函数的代码对比一下:
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 上不必要也用不到的属性【添加到子类构造函数原型对象上的父类构造函数属性】,因此可以说这个例子的效率更高。而且,原型链仍然保持不变,因此 instanceof 操作符和 isPrototypeOf()方法正常有效。寄生式组合继承可以算是引用类型继承的最佳模式。

浙公网安备 33010602011771号