news 2026/5/15 16:57:11

JavaScript继承大冒险:从“原型江湖”到“class殿堂”

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaScript继承大冒险:从“原型江湖”到“class殿堂”

引言:编程世界的“家族传承”

想象一下,你正在设计一个游戏角色系统。所有角色都有共通的属性:生命值、攻击力、移动速度…但法师会放火球,战士能开狂暴,盗贼可以潜行。你会为每个角色重复写相同的代码吗?当然不!这时候,继承就派上用场了!

今天,让我们一起探索JavaScript中继承的奇妙世界,看看这门语言是如何从ES5的“原型江湖”进化到ES6的“class殿堂”的。

🏰 第一站:ES5的“原型江湖”

什么是原型继承?

在ES5时代,JavaScript没有类(class)的概念,它玩的是原型链这套独门武功。每个对象都有一个隐秘的“祖宗”——原型对象(prototype)。

// 让我们从“人”这个基础开始functionPerson(name,age){this.name=name;this.age=age;}// 通过原型添加方法Person.prototype.sayHello=function(){console.log(`你好,我是${this.name},今年${this.age}`);};// 创建实例constzhangsan=newPerson('张三',25);zhangsan.sayHello();// 输出:你好,我是张三,今年25岁

原型继承的几种招式

招式1:原型链继承(最基础款)
functionStudent(name,age,grade){this.grade=grade;}// 关键一步:让Student的原型指向Person的实例Student.prototype=newPerson();Student.prototype.constructor=Student;// 修复构造函数指向Student.prototype.study=function(){console.log(`${this.name}正在学习,年级:${this.grade}`);};constxiaoming=newStudent('小明',16,'高一');xiaoming.sayHello();// 继承了Person的方法xiaoming.study();// 自己的方法

问题:所有实例共享同一个父类实例,一个修改,全家遭殃!

招式2:构造函数继承(借用父类构造函数)
functionStudent(name,age,grade){// 关键:在子类中调用父类构造函数Person.call(this,name,age);this.grade=grade;}constlisi=newStudent('李四',17,'高二');lisi.name;// 可以访问lisi.sayHello();// 报错!没有继承原型上的方法

问题:只能继承实例属性,原型方法没继承到!

招式3:组合继承(经典款)
functionStudent(name,age,grade){// 继承实例属性Person.call(this,name,age);this.grade=grade;}// 继承原型方法Student.prototype=newPerson();Student.prototype.constructor=Student;constwangwu=newStudent('王五',18,'高三');wangwu.sayHello();// 可以!wangwu.study();// 如果定义了,也可以!

缺点:调用了两次父类构造函数,有点浪费资源

招式4:寄生组合继承(终极完美版)
functioninheritPrototype(child,parent){// 创建一个以父类原型为原型的新对象constprototype=Object.create(parent.prototype);prototype.constructor=child;child.prototype=prototype;}functionStudent(name,age,grade){Person.call(this,name,age);this.grade=grade;}// 优雅地继承原型inheritPrototype(Student,Person);Student.prototype.study=function(){console.log(`${this.name}正在学习`);};

ES5继承流程图

渲染错误:Mermaid 渲染失败: Parse error on line 2: ...类构造函数
Parent.call(this, ...args)] -----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'PS'

🏛️ 第二站:ES6的“class殿堂”

ES6带来了class语法糖,让继承变得像喝咖啡一样简单!

class基础语法

// 用class定义父类classPerson{constructor(name,age){this.name=name;this.age=age;}sayHello(){console.log(`你好,我是${this.name},今年${this.age}`);}}// 用extends实现继承classStudentextendsPerson{constructor(name,age,grade){super(name,age);// 必须先调用super!this.grade=grade;}study(){console.log(`${this.name}正在${this.grade}学习`);}}// 使用起来超级简单constxiaohong=newStudent('小红',16,'高一');xiaohong.sayHello();// 继承的方法xiaohong.study();// 自己的方法

class的进阶特性

classTeacherextendsPerson{constructor(name,age,subject){super(name,age);this.subject=subject;}// 静态方法(类方法)staticgetProfession(){return'教师';}// getter/settergetteachingYears(){returnthis.age-22;// 假设22岁开始教书}setteachingYears(years){this.age=years+22;}// 方法重写sayHello(){super.sayHello();// 可以调用父类方法console.log(`我教${this.subject}`);}}console.log(Teacher.getProfession());// "教师"constmrWang=newTeacher('王老师',35,'数学');console.log(mrWang.teachingYears);// 13

🔍 终极对决:ES5 vs ES6继承

让我们通过一个对比表看清两者的区别:

特性ES5原型继承ES6 class
语法函数+原型链class关键字
继承方式手动设置原型链extends关键字
构造函数调用需要手动调用父构造函数通过super()调用
静态方法直接在构造函数上定义static关键字
私有字段没有原生支持#私有字段
代码可读性较低,理解成本高高,接近传统OOP
本质基于原型的继承语法糖,本质还是原型继承

可视化对比:继承的内部机制

ES6 class继承

class Person

内部创建构造函数和原型

class Student extends Person

自动设置原型链
通过super连接

语法简洁
底层还是原型

ES5原型继承

构造函数Person

Person.prototype

实例对象
__proto__指向原型

子类构造函数Student

Student.prototype = new Person

实例共享原型链

🎯 核心真相

ES6的class只是语法糖
底层仍然是基于原型的继承!

🎭 真实场景:游戏角色系统

让我们用两种方式实现同一个游戏角色系统:

ES5实现版

// 基础角色functionGameCharacter(name,hp){this.name=name;this.hp=hp;}GameCharacter.prototype.attack=function(){console.log(`${this.name}发起攻击!`);};// 战士functionWarrior(name,hp,strength){GameCharacter.call(this,name,hp);this.strength=strength;}// 设置原型链Warrior.prototype=Object.create(GameCharacter.prototype);Warrior.prototype.constructor=Warrior;Warrior.prototype.specialAttack=function(){console.log(`${this.name}使用狂暴斩击!伤害:${this.strength*2}`);};

ES6实现版

classGameCharacter{constructor(name,hp){this.name=name;this.hp=hp;}attack(){console.log(`${this.name}发起攻击!`);}}classWarriorextendsGameCharacter{constructor(name,hp,strength){super(name,hp);this.strength=strength;}specialAttack(){console.log(`${this.name}使用狂暴斩击!伤害:${this.strength*2}`);}}// 使用constconan=newWarrior('野蛮人柯南',100,15);conan.attack();// "野蛮人柯南发起攻击!"conan.specialAttack();// "野蛮人柯南使用狂暴斩击!伤害:30"

看到区别了吗?ES6版本明显更清晰、更易读!

💡 最佳实践与常见坑点

1. super()必须在使用this之前调用

classChildextendsParent{constructor(value){// ❌ 错误!必须先调用super// this.value = value;// super();// ✅ 正确super();this.value=value;}}

2. class中定义的方法是添加到原型上的

classMyClass{method1(){}// 在原型上method2=()=>{}// 在实例上(箭头函数)}// 等价于ES5functionMyClass(){this.method2=function(){};}MyClass.prototype.method1=function(){};

3. 继承内置类

classMyArrayextendsArray{// 可以自定义数组方法getfirst(){returnthis[0];}getlast(){returnthis[this.length-1];}}constarr=newMyArray(1,2,3);console.log(arr.first);// 1console.log(arr.last);// 3

🚀 总结:如何选择?

什么时候用ES5方式?

  • 维护老代码时
  • 需要深度控制原型链时
  • 环境不支持ES6时

什么时候用ES6 class?

  • 绝大多数情况下!
  • 新项目开发
  • 需要更好的可读性和维护性
  • 团队协作项目

结语:继承的哲学

JavaScript的继承演变告诉我们一个道理:好的语言特性应该让复杂的事情变简单,而不是让简单的事情变复杂

ES5的原型继承就像手动挡汽车——控制精细但操作复杂;ES6的class就像自动挡——简单易用,让开发者更专注于业务逻辑。

无论选择哪种方式,都要记住:理解底层的原型机制,才能真正掌握JavaScript的继承。毕竟,class只是华丽的包装,原型才是那颗不变的初心。

现在,你已经掌握了JavaScript继承的两种姿势。下次写代码时,你会选择留在"原型江湖",还是踏入"class殿堂"呢?🤔


互动时间:你在实际项目中遇到过哪些继承的坑?或者有什么有趣的继承使用场景?欢迎在评论区分享! 👇

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 13:32:57

R语言结构方程模型拟合失败?,5分钟定位4类常见问题并快速修正

第一章:R语言结构方程模型拟合失败的常见征兆在使用R语言进行结构方程模型(SEM)分析时,模型拟合失败是常见问题。识别这些失败的早期征兆有助于快速定位并修正模型设定或数据问题。非正定矩阵警告 当样本协方差矩阵出现负特征值或…

作者头像 李华
网站建设 2026/5/15 16:02:28

R语言中如何正确进行因子分析?90%的人都忽略了这3个关键点

第一章:R语言因子分析的核心概念与应用场景因子分析是一种用于探索观测变量背后潜在结构的多元统计方法,广泛应用于心理学、市场调研、社会科学和金融等领域。其核心思想是通过少数不可观测的潜变量(即“因子”)来解释多个观测变量…

作者头像 李华
网站建设 2026/5/9 10:34:30

ChanlunX缠论分析终极指南:快速掌握技术分析核心技能

想要在复杂多变的股市中精准把握买卖时机吗?ChanlunX缠论分析工具将深奥的技术分析理论转化为直观的可视化界面,让你轻松识别市场趋势和交易机会。无论你是投资新手还是有一定经验的分析师,本指南都将带你从基础入门到实战应用,全…

作者头像 李华
网站建设 2026/5/10 11:29:13

使用PyTorch框架加载IndexTTS 2.0模型进行语音合成

使用PyTorch框架加载IndexTTS 2.0模型进行语音合成 你有没有遇到过这样的场景:一段精心剪辑的视频,画面节奏紧凑、情绪到位,但旁白语速却慢半拍,导致音画错位?或者想让虚拟主播用你的声音说话,还要录几十分…

作者头像 李华
网站建设 2026/5/9 19:46:49

Botty完全指南:10分钟精通暗黑破坏神2重制版自动化运行

Botty是一款专为《暗黑破坏神2重制版》设计的开源自动化辅助工具,通过先进的图像识别技术模拟玩家操作,实现游戏内重复任务的智能化执行。无论你是新手玩家还是资深老鸟,Botty都能帮助你解放双手,享受更高效的游戏体验。 【免费下…

作者头像 李华
网站建设 2026/5/10 10:59:24

钉钉办公自动化:IndexTTS 2.0推送审批结果语音提醒

钉钉办公自动化:IndexTTS 2.0推送审批结果语音提醒 在企业协作日益数字化的今天,信息过载已成为一个隐形效率杀手。员工每天被成百上千条钉钉消息淹没,关键通知常常石沉大海——尤其是那些需要立即响应的审批结果。文本提醒容易被忽略&#…

作者头像 李华