当前位置: 首页 > article >正文

JavaScript 中的五种继承方式进行深入对比

文章目录

  • 前言
  • JavaScript 五种继承方式对比
    • 原型链继承
    • 构造函数继承
    • 组合继承
    • 寄生组合继承
    • ES6 class extends 继承
    • 五种继承方式对比表


前言

对 JavaScript 中的五种继承方式进行深入对比:原型链继承、构造函数继承、组合继承、寄生组合继承、以及 ES6 的 class extends。

内容将包括:

  • 每种方式的定义与核心原理
  • 示例代码
  • 优点与缺点分析
  • 应用场景与现代推荐

我整理好结构化的对比表格与说明文档后会立即通知你查看。

JavaScript 五种继承方式对比

JavaScript 的继承机制本质上是通过“原型链”将父类和子类关联起来。在 ES6 出现之前,开发者总结出了多种继承的经典实现方式,包括原型链继承构造函数继承组合继承寄生组合继承,以及 ES6 引入的 class extends 继承。下面将逐一分析这五种继承方式的实现原理、示例代码、优缺点(围绕属性共享、方法复用、实例隔离等方面),并给出适用场景建议。最后,我们提供一个对比表格,清晰展示这些方式在语法复杂度、性能、兼容性和多继承支持方面的差异。

原型链继承

实现原理与机制: 将子类的原型对象指向父类的一个实例,从而使子类实例的原型链上含有父类实例和父类的原型。这样,子类实例在访问属性或方法时,如果自身不存在,会沿着原型链在父类实例以及父类原型上查找,从而继承父类的属性和方法。

示例代码: 子类的原型指向父类实例,实现继承。注意此方式不调用父类构造函数,因此不能传参,也不会为每个子实例单独初始化父类属性。

function Parent() {this.name = "Parent";this.colors = ["red", "blue"];    // 引用类型属性
}
Parent.prototype.getName = function() {console.log("Name: " + this.name);
};function Child() {this.name = "Child";
}
// 子类原型指向父类实例,实现原型链继承
Child.prototype = new Parent();
Child.prototype.constructor = Child;  // (可选)修正constructor指向const child1 = new Child();
const child2 = new Child();
child1.colors.push("green");  
console.log(child1.colors, child2.colors);  // 输出: ["red","blue","green"] ["red","blue","green"] 
// 两个实例的 colors 引用同一个数组,修改一个会影响另一个
child1.getName();  // 输出: Name: Child
console.log(child1.getName === child2.getName);  // 输出: true (方法共享)

优点:

  • 子类通过原型链可以访问父类原型上的所有属性和方法,实现方法复用,共享父类的功能。如果父类原型新增方法/属性,子类实例也能访问到,维护成本低。
  • 实现简单,只需一行设置原型链,符合 JavaScript 原型继承的直观模型。

缺点:

  • 无法传参: 在创建子类实例时不能向父类构造函数传递参数(因为根本没有调用父构造函数)。每个子类实例无法定制父类初始化过程。
  • 引用属性共享: 父类构造函数里的引用类型属性(如数组、对象)会被所有子类实例共享,因为这些属性存在于同一个父类实例(即子类的原型对象)上。这导致实例不隔离 —— 一个实例修改了这些共享属性,会影响其他实例。上例中两个子实例的 colors 就指向同一数组。
  • 父类构造函数未在子类实例上执行,子类实例可能缺少父类构造函数中初始化的各自独立的属性值。如需每个实例拥有自己的副本,则无能为力。

适用场景: 原型链继承在需要共享方法且父类仅包含方法或静态属性时有用。但由于无法传参且存在引用属性共享问题,实际开发中很少单独使用。若父类含需单独初始化的属性(特别是引用类型),应考虑其他继承方式或在继承后手动屏蔽/重写这些属性。

构造函数继承

实现原理与机制: 在子类构造函数内部调用父类构造函数(通常使用 Parent.call(this, ...)apply),并将子类实例的 this 绑定给父类构造函数。这样,父类构造函数中定义的属性都会添加到子类实例上,实现对父类属性的继承。这种方式又称“借用构造函数”继承。

示例代码: 子类构造函数内部借用父类构造函数。由于没有建立原型链关系,父类原型方法不会自动继承下来。

function Parent(name) {this.name = name;this.colors = ["red", "blue"];  // 引用类型属性
}
Parent
http://www.lryc.cn/news/2380188.html

相关文章:

  • 企业标准信息公共服务平台已开放标准通编辑器访问入口
  • [Linux]安装吧!我的软件包管理器!
  • Spring Boot 与 RabbitMQ 的深度集成实践(三)
  • 进阶-数据结构部分:1、数据结构入门
  • React 19中useContext不需要Provider了。
  • Json schema校验json字符串(networknt/json-schema-validator库)
  • 交易所开发:构建功能完备的金融基础设施全流程指南
  • Windows_Vs2022 C#语言开发环境构建
  • Axure疑难杂症:统计分析页面引入Echarts示例动态效果
  • 展锐Android14及更新版本split_build编译方法
  • 青少年ctf平台应急响应-应急响应2
  • k8s监控方案实践补充(二):使用kube-state-metrics获取资源状态指标
  • WEB安全--SQL注入--Oracle注入
  • 基于SpringBoot的小型民营加油站管理系统
  • 每日一道leetcode(新学数据结构版)
  • 深入掌握MyBatis:连接池、动态SQL、多表查询与缓存
  • Bootstrap 5 容器与网格系统详解
  • Java反射机制详解:原理、应用与实战
  • 技术架构缺乏灵活性,如何应对变化需求?
  • 【AI时代】Java程序员大模型应用开发详细教程(上)
  • 虚拟网络编辑器
  • 102. 二叉树的层序遍历递归法:深度优先搜索的巧妙应用
  • Github 2025-05-16 Java开源项目日报 Top9
  • MinerU安装(pdf转markdown、json)
  • Java卡与SSE技术融合实现企业级安全实时通讯
  • 第31讲 循环缓冲区与命令解析
  • mapbox-gl强制请求需要accessToken的问题
  • 数据结构(十)——排序
  • 美蛋工具箱:一站式解决图片、视频、音频和文档处理需求的聚合神器
  • fastadmin 数据导出,设置excel行高和限制图片大小