全面解析 JavaScript 类继承:方式、优缺点与应用场景

在 JavaScript 中,"继承"指的是让一个对象或类能够复用另一个对象或类的属性和方法。

由于 JavaScript 的面向对象机制是基于 原型(prototype) 而非传统类,因此继承方式丰富多样,从 ES5 时代的手动原型链,到 ES6 之后的 class 语法糖,都有不同的实现手段。

本文将系统介绍 8 种主要继承方式 ,分析它们的优缺点适用场景,并提供代码示例。


1. class 继承(ES6 extends

js 复制代码
class Parent {
  greet() { console.log("Hello from Parent"); }
}
class Child extends Parent {
  greet() { super.greet(); console.log("...and from Child"); }
}
new Child().greet();

优点

  • 语法简洁,接近 Java / C# 等语言。
  • 内置 super 调用父类构造和方法。
  • 支持继承内置对象(Array, Error 等)。
  • 性能接近最佳(底层是寄生组合继承)。

缺点

  • 只是语法糖,本质仍是原型链。
  • 高级场景(动态改继承结构)需理解原型机制。

适用场景

  • 现代前端、Node.js 项目的默认选择。

2. class + 表达式继承(动态继承)

js 复制代码
function mixin(base) {
  return class extends base {
    extra() { console.log("extra"); }
  }
}
class Parent {}
class Child extends mixin(Parent) {}
new Child().extra();

优点

  • 运行时动态决定父类。
  • 易于组合多个基类。

缺点

  • 可读性差,调试困难。

适用场景

  • 插件系统、UI 组件动态扩展。

3. 原型链继承

js 复制代码
function Parent() { this.colors = ["red", "blue"]; }
Parent.prototype.say = function() { console.log("parent"); };

function Child() {}
Child.prototype = new Parent();
Child.prototype.constructor = Child;

优点

  • 实现简单。
  • 子类可直接访问父类原型方法。

缺点

  • 属性被所有实例共享(引用类型容易出错)。
  • 无法向父类构造传参。

适用场景

  • 学习原型链原理,已不推荐在生产使用。

4. 借用构造函数继承

js 复制代码
function Parent(name) { this.name = name; }
function Child(name) { Parent.call(this, name); }

优点

  • 每个实例的属性独立。
  • 可传参。

缺点

  • 无法继承父类原型方法,方法需重复定义。

适用场景

  • 仅继承属性,不需要父类方法的简单对象。

5. 组合继承

js 复制代码
function Parent(name) { this.name = name; }
Parent.prototype.say = function() { console.log(this.name); };

function Child(name) {
  Parent.call(this, name); // 继承属性
}
Child.prototype = new Parent(); // 继承方法
Child.prototype.constructor = Child;

优点

  • 继承父类属性与方法。
  • 子类实例独立。

缺点

  • 父类构造函数被调用两次。

适用场景

  • ES5 最常用方式,简单可靠。

6. 寄生组合继承

js 复制代码
function inherit(Child, Parent) {
  Child.prototype = Object.create(Parent.prototype);
  Child.prototype.constructor = Child;
}
function Parent(name) { this.name = name; }
Parent.prototype.say = function() { console.log(this.name); };

function Child(name) {
  Parent.call(this, name);
}
inherit(Child, Parent);

优点

  • 父类构造只调用一次,性能好。
  • 完整继承属性和方法。

缺点

  • 写法比组合继承稍复杂。

适用场景

  • ES5 推荐的最佳继承方案。

7. 原型式继承

js 复制代码
let parent = { greet() { console.log("hello"); } };
let child = Object.create(parent);
child.greet();

优点

  • 极简,无需构造函数。
  • 灵活,适合快速克隆对象。

缺点

  • 属性共享,引用类型有风险。
  • 无法传参初始化。

适用场景

  • 创建配置模板、数据对象。

8. 寄生式继承

js 复制代码
function createChild(o) {
  let clone = Object.create(o);
  clone.say = function() { console.log("hi"); };
  return clone;
}
let parent = { greet() { console.log("hello"); } };
let child = createChild(parent);
child.say();

优点

  • 在原型式继承基础上增强对象。
  • 灵活度高。

缺点

  • 方法无法复用,浪费内存。

适用场景

  • 一次性对象增强。

9. Mixin 混入

js 复制代码
const sayMixin = { say() { console.log("hi"); } };
class Person {}
Object.assign(Person.prototype, sayMixin);

优点

  • 模拟多继承。
  • 灵活扩展功能。

缺点

  • 命名冲突风险。
  • 方法来源分散,不易维护。

适用场景

  • 事件系统、功能扩展。

继承方式对比表

方式 优点 缺点 推荐度 场景
class 继承 语法简洁,支持 super 语法糖,本质是原型链 ⭐⭐⭐⭐⭐ 现代项目
class + 表达式 动态父类 可读性差 ⭐⭐⭐ 插件系统
原型链继承 简单直观 属性共享,不能传参 学习原理
借用构造函数 属性独立,可传参 不继承方法 ⭐⭐ 仅需属性
组合继承 属性独立+继承方法 调用两次父构造 ⭐⭐⭐⭐ ES5 常用
寄生组合继承 性能最佳 写法稍复杂 ⭐⭐⭐⭐⭐ ES5 推荐
原型式继承 极简 属性共享 ⭐⭐ 对象克隆
寄生式继承 灵活增强 无法复用方法 ⭐⭐ 一次性增强
Mixin 多继承效果 命名冲突风险 ⭐⭐⭐ 功能扩展

结语

  • 如果是 现代项目 :优先使用 class extends
  • 如果是 ES5 项目 :用 寄生组合继承
  • 如果只是克隆/增强对象:用 Object.createMixin
  • 学习原型链原理时,可以用最简单的原型链继承练习。

理解继承方式,不仅是写代码的技巧,更是掌握 JavaScript 对象模型的关键。

相关推荐
gnip10 分钟前
axios 拦截器实现用户无感刷新 access_token
前端
程序员码歌18 分钟前
【零代码AI编程实战】AI灯塔导航-成果展示篇
前端·ai编程·cursor
gnip26 分钟前
前端实现即时通讯,常用的技术
前端
烛阴1 小时前
告别 any!用联合类型打造更灵活、更安全的 TS 代码
前端·typescript
用户21411832636022 小时前
dify案例分享-100% 识别率!发票、汇票、信用证全搞定的通用票据识别工作流
前端
拾光拾趣录3 小时前
基础 | HTML语义、CSS3新特性、浏览器存储、this、防抖节流、重绘回流、date排序、calc
前端·面试
小小小小宇4 小时前
前端监测用户卡顿之INP
前端
小小小小宇4 小时前
监测用户在浏览界面过程中的卡顿
前端
糖墨夕4 小时前
Nest 是隐藏的“设计模式大佬”
前端