JavaScript 系列 - 继承

101 阅读2分钟

原型继承

  • SubType.prototype = SuperType.prototype

    相互影响

  • SubType.prototype = new SuperType()

    • 无关函数就会影响后代
    • 包含引用类型的原型属性会被所有实例属性共享,容易造成属性的修改混乱
    • 在创建子类型的实例时,不能向超类型的构造函数中传递参数
// 原型继承
function SuperType(colors) {
  this.colors = colors;
}
SuperType.prototype.getColors = function () {
  return this.colors;
};
function SubType(subProperty) {
  this.subProperty = subProperty;
}
SubType.prototype = new SuperType(["red", "blue", "green"]);
SubType.prototype.constructor = SubType;
SubType.prototype.getSubProperty = function () {
  console.log(this.subProperty);
};
let instance1 = new SubType("subProperty1");
let instance2 = new SubType("subProperty2");
console.log(instance1, instance2);

借用父级函数

SuperType.call(this,"property")

  • 只能在父级中定义方法,每个子类都会实例方法
  • 子类不能访问父类原型上的方法
// 借用父级函数
function SuperType(colors) {
  this.colors = colors;
  this.getColors = function () {
    return this.colors;
  };
}
SuperType.prototype.function = function () {
  return "function";
};
function SubType(colors, subProperty) {
  SuperType.call(this, colors);
  this.subProperty = subProperty;
}
let instance1 = new SubType("red", "subProperty1");
let instance2 = new SubType("blue", "subProperty2");
//   只能在父级中定义方法,每个子类都会实例方法
//   子类不能访问父类原型的方法
console.log(instance1, instance2);

组合继承

  • instanceof 和 isPropertyOf() 也能够用于识别基于组合继承创建的对象
  • 基类的原型对象中增添了不必要的超类的实例对象中的所有属性
  • 父级函数调用两次
// 组合继承
function SuperType(colors) {
  this.colors = colors;
}
SuperType.prototype.getColors = function () {
  console.log(this.colors);
};
function SubType(colors, subProperty) {
  //继承属性
  SuperType.call(this, colors);
  this.subProperty = subProperty;
}
//继承方法
SubType.prototype = new SuperType(["red", "blue", "green"]);
SubType.prototype.constructor = SubType;
SubType.prototype.getSubProperty = function () {
  console.log(this.subProperty);
};
var instance1 = new SubType("red", "subProperty1");
var instance2 = new SubType("blue", "subProperty2");
console.log(instance1, instance2);

原型式继承

  • Object.create
    • 不必创建构造函数
    • 一个是传参的问题,一个是引用类型属性共享的问题
  • 扩展一个存在对象
// 原型式继承
var person = {
  name: "Nicholas",
  friends: ["Shelby", "Crt", "Van"],
};
var anotherPerson = Object.create(person, {
  name: {
    value: "Greg",
  },
});
console.log(anotherPerson);

寄生式继承

  • 函数内部创建一个对象进行增强然后返回
    • 增强功能无法函数复用
  • 对象之间继承
// 寄生式继承
function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}
function createAnother(original) {
  // 通过调用函数创建一个新对象
  var clone = object(original);
  clone.sayHi = function () {
    // 某种方式增强这个对象
    console.log("hi");
  };
  return clone; // 返回这个对象
}
var person = {
  name: "james",
};
var anotherPerson = createAnother(person);

寄生式组合继承

  • 解决两次调用
  • 避免了在 SubType.prototype 上创建不必要的属性
  • 与此同时还能保持原型链不变
// 寄生式组合继承
function SuperType(colors) {
  this.colors = colors;
}
SuperType.prototype.getColors = function () {
  console.log(this.colors);
};
function SubType(colors, subProperty) {
  // 继承属性
  SuperType.call(this, colors);
  this.subProperty = subProperty;
}
// 继承方法
// subType.prototype = Object.create(superType.prototype);
SubType.prototype = object(superType.prototype);
SubType.prototype.constructor = SubType;
SubType.prototype.getSubProperty = function () {
  console.log(this.subProperty);
};
var instance1 = new SubType("red", true);
var instance2 = new SubType("blue", false);
console.log(instance1, instance2);