JavaScript 继承

2025-07-19 · 修改于 2025-07-22

龙生龙、凤生凤,老鼠的孩子会打洞。

继承是面向对象编程的四大基本特征之一(继承、封装、多态和抽象),它遵循 里氏替换原则,允许子类替换父类而不影响程序的正确性。


多种继承方式

原型继承

在理解原型链继承之前,先了解一下 JavaScript 中的对象引用和方法调用。

js
const o = {
  name: 'Alice',
  age: 20,
  sayHello() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

const p = Object.create(o);

原型链继承的本质是对象引用和方法调用。通过对象引用的方式实现属性和方法共享,通过方法调用的方式改变 this 指向。

js
function Person(name) {
  this.name = name;
}
Person.prototype.speak = function() {
  console.log(`${this.name} said "How are you?".`);
}

function Student(name) {
  // 调用父类构造函数,可以为父类构造函数传参
  Person.call(this, name);
}

// 因为方法都在原型上,所以我们可以直接让 Student 的原型指向 Person 的原型
Student.prototype = Object.create(Person.prototype);
// 确保 Student 的构造函数指向 Student(修复 this 指向问题)
Student.prototype.constructor = Student;

const student = new Student('John');
student.speak();

类继承

ES6 引入的 class 和 extends 关键字,提供更简洁的语法糖,本质上仍是基于原型的继承。

js
class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name); // 调用父类构造函数
  }
  speak() {
    console.log(`${this.name} barks.`);
  }
}

const dog = new Dog('Rex');
dog.speak(); // 输出: Rex barks.

原型继承 vs 类继承

特性原型继承类继承
语法基于对象和 prototype 属性基于 class 和 extends 关键字
可维护性相对较难维护更易读和维护
多重继承需要手动实现不直接支持
框架支持传统方式现代框架常用方式

继承的优缺点

优点

  • 代码复用:子类可以复用父类的方法
  • 层次清晰:形成类的层次结构
  • 易于扩展:新增子类不影响已有代码

缺点

  • 父类变更影响子类
  • 不同实现方式可能导致混乱
  • 继承层次过深会影响性能

使用继承的最佳实践

  1. 优先考虑组合而非继承
  2. 明确继承关系的"is-a"语义
  3. 保持继承层次简洁
  4. 注意继承中的属性共享问题
  5. 了解并合理使用 ES6 类的继承语法糖
Author's avatar

专注计算机科学与技术

鼓励作者

感谢你赐予我前进的动力!

微信
支付宝
© 版权声明: 此文章为作者原创文章,采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源!

基于 MIT 许可发布

版权所有 © 2024-2025 向成渝