前端学习笔记-JavaScript继承(二)

92 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

原型式继承(补充)

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上不必要也用不到的属性,且原型链仍然保持不变。

总结

  • 原型式继承可以无须明确定义构造函数而实现继承,本质上是对给定对象执行浅复制。这种操作的结果之后还可以再进一步增强。

  • 与原型式继承紧密相关的是寄生式继承,即先基于一个对象创建一个新对象,然后再增强这个新对象,最后返回新对象。这个模式也被用在组合继承中,用于避免重复调用父类构造函数导致的浪费。

  • 寄生组合继承被认为是实现基于类型继承的最有效方式。