babel将class降级为构造函数并插入_classcallcheck检查,确保必须用new调用;继承通过object.create、constructor修复和__proto__设置实现寄生组合式继承;super()编译为parent.call(this)以初始化this。

直接看 Babel 编译后的代码,是理解 class 降级最扎实的方式。它不靠理论猜,而是把语法糖“剥开”,露出底层的函数、原型链和检查逻辑——这才是兼容性落地的真实样子。
看清 class 被转成什么:构造函数 + new 检查
ES6 的 class Person 不是新东西,Babel 会把它编译成一个普通函数,并立刻插入 _classCallCheck 调用:
- 这个函数用
instance instanceof Constructor判定调用方式 - 如果用
Person()直接调用,this不是Person实例,就抛出 "Cannot call a class as a function" - 只有
new Person()才能让this正确绑定,检查通过
这比 ES5 更严格,堵住了遗漏 new 导致的 this 错乱问题。
继承不是魔法:extends 对应三步原型操作
class Child extends Parent 看似简洁,Babel 编译后实际做了三件事:
- 让
Child.prototype的__proto__指向Parent.prototype(用Object.create(Parent.prototype)) - 把
Child.prototype.constructor重设回Child,避免构造器丢失 - 设置
Child.__proto__ = Parent,使静态方法(如Parent.method())能被Child继承
整个过程完全复刻寄生组合式继承,但自动完成,不依赖手动写 call 或 create。
super() 的真实作用:初始化 this 并承接父类属性
子类构造函数中 super() 不是可选语法糖,而是强制步骤:
- 它本质是执行
Parent.call(this, ...args),把父类的实例属性(如this.name)挂到当前this上 - 没调
super就访问this,会报错 —— 因为子类没有自己的this,必须先由父类构造函数生成 - 在方法里写
super.xxx(),等价于Parent.prototype.xxx.call(this)
这解释了为什么 Babel 编译后,子类构造函数第一行永远是 Parent.call(this, ...)。
验证兼容性:instanceof 和原型链没变
降级不是妥协,而是保真。一个 new Child() 实例,在编译产物中依然满足:
child instanceof Child === truechild instanceof Parent === true- 原型链仍是:
child.__proto__ → Child.prototype → Parent.prototype → Object.prototype
这意味着所有基于原型链的判断(包括第三方库的类型校验)都能照常工作,兼容性有底层保障。
不复杂但容易忽略:Babel 的降级不是“翻译”,而是“重构”——它用 ES5 可靠的原语,重建了 class 的约束、关系与行为,让新语法在老环境里稳稳运行。











