本文已参与「新人创作礼」活动,一起开启掘金创作之路。
原型式继承(补充)
Object.create()即为原型式继承的封装,不过它还可以传递第二个参数
(与Object.defineProperties()的第二个参数一样:每个新增属性都通过各自的描述符来描述)
梳理:工厂模式,创建临时空的构造函数,用现有对象作为原型,返回实例化的结果;可共享原型对象的属性和方法
寄生式继承
依然不创建自己的构造函数 可把子类的方法放在这个工厂函数中
function createAnother(original){
let clone = Object.create(original); // 通过调用函数创建一个新对象
clone.sayHi = function() { // 以某种方式增强这个对象
console.log("hi");
};
return clone; // 返回这个对象
}
同样适合主要关注对象,而不在乎类型和构造函数的场景。
缺点是给对象添加函数会导致函数难以重用,与构造函数模式类似。
梳理:原型式继承的改进,在工厂函数中浅拷贝结果上添加共享方法
寄生组合式继承
组合继承存在效率问题:父类构造函数被调用两次;
神三元版:组合式继承中 的首次调用被替换为寄生继承 不产生父类的实例 直接使用其原型对象 因此少一次调用。
红宝书版:
function inheritPrototype(subType, superType) {
let prototype = object(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上不必要也用不到的属性,且原型链仍然保持不变。
总结
-
原型式继承可以无须明确定义构造函数而实现继承,本质上是对给定对象执行浅复制。这种操作的结果之后还可以再进一步增强。
-
与原型式继承紧密相关的是寄生式继承,即先基于一个对象创建一个新对象,然后再增强这个新对象,最后返回新对象。这个模式也被用在组合继承中,用于避免重复调用父类构造函数导致的浪费。
-
寄生组合继承被认为是实现基于类型继承的最有效方式。