JavaScript class 是原型继承的语法糖,Babel 将其转为构造函数、挂载方法到 prototype 或构造函数自身,并用 Object.defineProperty 处理 getter/setter 和不可枚举性。

JavaScript 的 class 语法本质上是原型继承的语法糖,Babel 的作用就是把它“脱糖”,还原成 ES5 兼容的函数和原型操作。核心逻辑是:把 class 声明转为构造函数,把 method 挂到 prototype 上,把 static 方法挂到构造函数自身,再用 Object.defineProperty 处理 getter/setter 和不可枚举性。
基础 class 编译为构造函数 + prototype
例如:
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
return `Hello, ${this.name}`;
}
}
Babel(配合 @babel/preset-env)会编译为:
"use strict";
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
var Person = /*#__PURE__*/_createClass(function Person(name) {
_classCallCheck(this, Person);
this.name = name;
}, [{
key: "sayHello",
value: function sayHello() {
return "Hello, " + this.name;
}
}]);
说明:
立即学习“Java免费学习笔记(深入)”;
-
_classCallCheck实现new调用检查,防止直接调用构造函数 -
_createClass封装了原型方法和静态方法的定义逻辑 -
_defineProperties使用Object.defineProperty确保方法不可枚举(符合 class 行为)
继承(extends)编译为寄生组合式继承
比如:
class Student extends Person {
constructor(name, grade) {
super(name);
this.grade = grade;
}
study() {
return `${this.name} is studying`;
}
}
会被编译为(关键部分):
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: { value: subClass, writable: true, configurable: true }
});
Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
var Student = /*#__PURE__*/function (_Person) {
_inherits(Student, _Person);
function Student(name, grade) {
var _this;
_classCallCheck(this, Student);
_this = _callSuper(this, Student, [name]);
_this.grade = grade;
return _this;
}
_createClass(Student, [{
key: "study",
value: function study() {
return this.name + " is studying";
}
}]);
return Student;
}(Person);
说明:
立即学习“Java免费学习笔记(深入)”;
-
_inherits实现标准寄生组合式继承:设置子类原型为父类原型的副本,并修正constructor -
_callSuper(内部由_get等辅助函数支持)处理super()调用,确保正确绑定this并调用父类构造器
静态方法、getter/setter 和私有字段的处理
Babel 对不同特性采用不同策略:
-
静态方法:直接通过
_defineProperties(Student, [...])挂在构造函数上 -
getter/setter:在
_defineProperties中生成带get/set属性的 descriptor -
私有字段(#field)和私有方法:需启用
@babel/plugin-proposal-private-methods和@babel/plugin-proposal-class-properties,编译后使用 WeakMap 或闭包模拟私有性,不直接暴露在原型上
实际打包中需要注意的配置
确保 Babel 正确降级 class,需满足:
- 安装并启用
@babel/preset-env(它已内置 class 相关插件) - 目标环境(
targets)设为需要兼容的浏览器版本(如{"chrome": "49"}),Babel 会自动决定是否需要转换 class - 若显式使用插件,优先用
@babel/plugin-transform-classes,它比手动配一堆插件更可靠
不复杂但容易忽略。


















