对象继承的6种方式

54 阅读2分钟

参考《JavaScript高级程序设计》(第四版)8.3 继承

原型链继承

缺点

  1. 原型包含引用类型时,所有实例会共享,造成修改混乱
  2. 创建子类不能向超类传参
function SuperType() {
  this.name = 'super';
  this.colors = ['red']
}
SuperType.prototype.sayName = function() {
  console.log(this.name);
}
function SubType(age) {
  this.age = age;
}
SubType.prototype = new SuperType();
const s1 = new SubType(10);
s1.colors.push('yellow')
console.log(s1);
s1.sayName();

运行结果

image.png

盗用构造函数继承

优点

  1. 解决了原型链继承不能传参的问题。

缺点

  1. 超类原型上的方法,子类不能使用
  2. 函数不能复用,因为必须在构造函数内部定义方法。
function SuperType(name) {
  this.name = name;
  this.colors = ['red'];
  this.sayHi = function() {
    console.log('HI');
  }
}
SuperType.prototype.sayName = function() {
  console.log(this.name);
}
function SubType(age, name) {
  SuperType.call(this, name)
  this.age = age;
}
const s1 = new SubType(10, 'Tom');
console.log(s1);

运行结果

1700727429475.png

组合继承

优点

  1. 解决了上述2种方式单独使用造成的问题

缺点

  1. 因为调用了2次超类构造函数,所有造成子类原型拥有很多不需要的属性。
function SuperType(name) {
  this.name = name;
  this.colors = ['red'];
}
SuperType.prototype.sayName = function() {
  console.log(this.name);
}
function SubType(age, name) {
  SuperType.call(this, name)
  this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
const s1 = new SubType(10, 'Tom');
console.log(s1);

运行结果

1700728106981.jpg

原型式继承

用途:主要是为了实现对一个对象的简单继承,不是为了实现创造一个新的类型。

缺点

  1. 引用类型的问题。
function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}
let person = {
  name: 'Lisa',
  friends: ['Ann']
}
let anotherPerson = object(person);
anotherPerson.name = 'Tom';
anotherPerson.friends.push('Rob');

let anotherPerson2 = object(person);
anotherPerson2.name = 'Lily';
anotherPerson2.friends.push('Bob');

console.log(anotherPerson,anotherPerson2)

运行结果

1700728336004.png

寄生式继承

优点:可以实现对一个简单的对象继承,然后做扩展。

缺点:不能复用。

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"
 console.log(anotherPerson)

运行结果

image.png

寄生式组合继承

优点:解决组合继承会给子类原型添加不必要属性的问题。

function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}
function inheritPrototype(subType, superType) {
  let prototype = object(superType.prototype);
  subType.prototype = prototype;
  subType.prototype.constructor = subType;
}
function SuperType(name) {
  this.name = name;
  this.colors = ['red'];
}
SuperType.prototype.sayName = function() {
  console.log(this.name);
}
function SubType(age, name) {
  SuperType.call(this, name)
  this.age = age;
}
inheritPrototype(SubType, SuperType);
const s1 = new SubType(10, 'Tom');
console.log(s1);

运行结果

image.png