35. JS 中常见继承方式对比总结 副本.md

查看飞书原文 ↗5,693 字符

1. 核心概念 (Core Concept)

JavaScript 中的继承是一种机制,允许一个对象(或构造函数)“继承”另一个对象(或构造函数)的属性和方法。这意味着子对象可以访问父对象定义的属性和方法,从而实现代码的复用和构建对象之间的层级关系。

2. 为什么需要它? (The "Why")

3. API 与用法 (API & Usage)

JavaScript 提供了多种实现继承的方式,主要包括:

以下是几种常见方式的纯粹示例,展示核心机制:

原型链继承 (Prototype Chain Inheritance):

function Parent() {
  this.name = 'parent';
  this.colors = ['red', 'blue'];
}

Parent.prototype.sayName = function() {
  console.log(this.name);
};

function Child() {
  this.age = 10;
}

// 核心:将子类型的原型指向父类型的实例
Child.prototype = new Parent(); // 注意:这里会创造一个不必要的 Parent 实例
Child.prototype.constructor = Child; // 修复 constructor 指向

Child.prototype.sayAge = function() {
  console.log(this.age);
};

const instance1 = new Child();
instance1.sayName(); // 输出 'parent'
console.log(instance1.colors); // 输出 ['red', 'blue']
instance1.colors.push('green');
console.log(instance1.colors); // 输出 ['red', 'blue', 'green']

const instance2 = new Child();
console.log(instance2.colors); // 输出 ['red', 'blue', 'green'] - 说明引用类型的属性被所有实例共享

构造函数继承 (Constructor Function Inheritance):

function Parent() {
  this.name = 'parent';
  this.colors = ['red', 'blue'];
}

function Child() {
  // 核心:在子类型构造函数中调用父类型构造函数
  Parent.call(this); // or Parent.apply(this)
  this.age = 10;
}

const instance1 = new Child();
instance1.colors.push('green');
console.log(instance1.colors); // 输出 ['red', 'blue', 'green']

const instance2 = new Child();
console.log(instance2.colors); // 输出 ['red', 'blue'] - 引用类型属性不再共享
console.log(instance1.name); // 输出 'parent'
console.log(instance2.name); // 输出 'parent'

// 注意:Parent.prototype 上的方法不会被继承
// instance1.sayName(); // 报错:instance1.sayName is not a function

组合继承 (Combination Inheritance):

function Parent() {
  this.name = 'parent';
  this.colors = ['red', 'blue'];
}

Parent.prototype.sayName = function() {
  console.log(this.name);
};

function Child() {
  // 继承属性
  Parent.call(this);
  this.age = 10;
}

// 继承方法
Child.prototype = new Parent(); // 问题:调用了两次 Parent 构造函数
Child.prototype.constructor = Child;

Child.prototype.sayAge = function() {
    console.log(this.age);
};

const instance1 = new Child();
instance1.colors.push('green');
console.log(instance1.colors); // 输出 ['red', 'blue', 'green']
instance1.sayName(); // 输出 'parent'

const instance2 = new Child();
console.log(instance2.colors); // 输出 ['red', 'blue']
instance2.sayName(); // 输出 'parent'

寄生组合式继承 (Parasitic Combination Inheritance): (公认最优方案)

function inheritPrototype(child, parent) {
    // 创建一个空对象作为中介,避免直接实例化父类
    const prototype = Object.create(parent.prototype);
    prototype.constructor = child; // 增强对象,指定 constructor
    child.prototype = prototype; // 将子类型的原型指向这个中介对象
}

function Parent() {
  this.name = 'parent';
  this.colors = ['red', 'blue'];
}

Parent.prototype.sayName = function() {
  console.log(this.name);
};

function Child() {
  // 继承属性
  Parent.call(this);
  this.age = 10;
}

// 继承方法
inheritPrototype(Child, Parent);

Child.prototype.sayAge = function() {
    console.log(this.age);
};

const instance1 = new Child();
instance1.colors.push('green');
console.log(instance1.colors); // 输出 ['red', 'blue', 'green']
instance1.sayName(); // 输出 'parent'

const instance2 = new Child();
console.log(instance2.colors); // 输出 ['red', 'blue']
instance2.sayName(); // 输出 'parent'

console.log(instance1 instanceof Child); // true
console.log(instance1 instanceof Parent); // true

ES6 Class (语法糖):

class Parent {
  constructor() {
    this.name = 'parent';
    this.colors = ['red', 'blue'];
  }

  sayName() {
    console.log(this.name);
  }
}

class Child extends Parent {
  constructor() {
    // 核心:调用父类构造函数
    super();
    this.age = 10;
  }

  sayAge() {
    console.log(this.age);
  }
}

const instance1 = new Child();
instance1.colors.push('green');
console.log(instance1.colors); // 输出 ['red', 'blue', 'green']
instance1.sayName(); // 输出 'parent'

const instance2 = new Child();
console.log(instance2.colors); // 输出 ['red', 'blue']
instance2.sayName(); // 输出 'parent'

console.log(instance1 instanceof Child); // true
console.log(instance1 instanceof Parent); // true

4. 关键注意事项 (Key Considerations)

5. 参考资料 (References)


原文链接与附件索引