javascript ES6类如何定义_它是否彻底改变了继承机制?

发布时间 - 2026-01-02 00:00:00    点击率:
ES6 class 是语法糖,本质仍是原型链继承,所有继承基于[[Prototype]]链,class声明编译为构造函数并自动设置prototype和constructor,extends通过Object.setPrototypeOf实现继承。

ES6 class 只是语法糖,底层仍是原型链继承

它没有改变 JavaScript 的继承机制本质——所有继承依然基于 [[Prototype]] 链。所谓“类”,只是把原本用 function + prototype + Object.setPrototypeOf 手动搭的结构,包装成更接近传统 OOP 语言的写法。

真正执行时,class 声明会被编译为构造函数,并自动设置 prototypeconstructor 属性;extends 则会调用 Object.setPrototypeOf(SubClass, SuperClass)Object.setPrototypeOf(SubClass.prototype, SuperClass.prototype)

  • class 内部方法默认不可枚举(比手写 prototype 更干净)
  • class 声明不会被提升(而函数声明会),且必须用 new 调用,否则报 TypeError: Class constructor X cannot be invoked without 'new'
  • 静态方法和实例方法都通过 prototype 或构造函数本身挂载,没新增任何底层机制

如何正确定义 class 并实现继承?

关键在三步:定义基类、用 extends 继承、子类中必须调用 super()(哪怕不传参)。

class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    return `${this.name} makes a sound.`;
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // ← 必须!否则报 ReferenceError
    this.breed = breed;
  }
  speak() {
    return `${this.name} barks.`;
  }
}
  • 不写 constructor 时,子类会自动获得默认构造函数:constructor(...args) { super(...args); }
  • super() 必须在访问 this 之前调用,否则报 ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
  • 静态方法也能被继承:Dog.isAnimal = true 不会覆盖从 Animal 继承来的 isAnimal,但可通过 static get isAnimal() { return true; } 显式定义

为什么 instanceofObject.getPrototypeOf 仍能准确反映真实关系?

因为 class 没有绕过原型系统,只是让原型链更“规整”。你可以用原生 API 验证它的底层结构:

const dog = new Dog('Max', 'Golden');
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
console.log(Object.getPrototypeOf(dog) === Dog.prototype); // true
console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // true
  • Dog.prototype.__proto__ 指向 Animal.prototype(尽管不推荐直接用 __proto__
  • Dog.__proto__ 指向 Animal,这决定了静态属性/方法的继承链
  • 如果你手动修改 Dog.prototype(比如赋值为新对象),会断开与 Animal.prototype 的连接,instanceof 就会失效

容易被忽略的细节:私有字段、new.target 和装饰器兼容性

ES6 class 本身不支持私有成员,直到 ES2025 才加入 #field 语法;而 new.targetclass 构造器中行为更严格——它能区分是否被 new 调用,这对编写可继承的工具类很关键。

  • 私有字段 #name 是真正的私有(无法被子类访问),不是命名约定(如 _name
  • new.target 在基类构造器中指向实际被 new 的类(比如 new Dog() 时,new.target === Dog),可用于防止类被直接实例化
  • 目前主流装饰器提案(如 @bound)依赖 Babel 或 TypeScript 转译,原生 class 不支持运行时装饰,这点常被误认为是“类的限制”

真正复杂的地方在于:你得同时理解语法糖表象和原型链实质。一旦遇到奇怪的 instanceof 失败、this 绑定异常或继承链断裂,问题几乎总出在原型操作被意外覆盖,而不是 class 本身。


# javascript  # es6  # java  # go  # typescript  # access  # 工具  # 为什么  # speak 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: JS实现鼠标移上去显示图片或微信二维码  利用vue写todolist单页应用  微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】  Linux网络带宽限制_tc配置实践解析【教程】  PHP 实现电台节目表的智能时间匹配与今日/明日轮播逻辑  Python文本处理实践_日志清洗解析【指导】  悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音  Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】  PythonWeb开发入门教程_Flask快速构建Web应用  如何在腾讯云服务器上快速搭建个人网站?  Laravel如何使用.env文件管理环境变量?(最佳实践)  如何安全更换建站之星模板并保留数据?  如何快速打造个性化非模板自助建站?  谷歌Google入口永久地址_Google搜索引擎官网首页永久入口  如何在Windows环境下新建FTP站点并设置权限?  如何用美橙互联一键搭建多站合一网站?  linux写shell需要注意的问题(必看)  简单实现Android文件上传  Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤  如何有效防御Web建站篡改攻击?  如何用PHP快速搭建高效网站?分步指南  制作旅游网站html,怎样注册旅游网站?  网易LOFTER官网链接 老福特网页版登录地址  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  如何在建站主机中优化服务器配置?  如何在建站宝盒中设置产品搜索功能?  微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  如何彻底卸载建站之星软件?  python中快速进行多个字符替换的方法小结  手机软键盘弹出时影响布局的解决方法  小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?  Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程  Laravel路由怎么定义_Laravel核心路由系统完全入门指南  详解jQuery中的事件  如何正确选择百度移动适配建站域名?  如何自定义建站之星网站的导航菜单样式?  PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】  三星、SK海力士获美批准:可向中国出口芯片制造设备  如何快速搭建高效WAP手机网站?  android nfc常用标签读取总结  高防服务器租用首荐平台,企业级优惠套餐快速部署  Laravel怎么定时执行任务_Laravel任务调度器Schedule配置与Cron设置【教程】  Laravel Fortify是什么,和Jetstream有什么关系  Laravel模型事件有哪些_Laravel Model Event生命周期详解  如何快速建站并高效导出源代码?  Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】  html5如何实现懒加载图片_ intersectionobserver api用法【教程】  高端企业智能建站程序:SEO优化与响应式模板定制开发  图册素材网站设计制作软件,图册的导出方式有几种?