Babel 插件,自动在 class 中插入 static {} 块,将实例字段标记到 prototype 上。目的是让运行时代码能在实例创建前就提前知道有哪些字段。
输入:
const TAG = "tag";
class Animal {
static count = 0;
name;
type = "dog";
[TAG];
legs = 4;
}输出:
const TAG = "tag";
class Animal {
static {
this.prototype.name = undefined;
this.prototype.type = undefined;
this.prototype[TAG] = undefined;
this.prototype.legs = undefined;
}
static count = 0;
name;
type = "dog";
[TAG];
legs = 4;
}static {} 中的 this 指向类自身,因此对具名类和匿名类均有效:
// 匿名类同样支持
const Cat = class {
name;
};
// → 自动生成 static { this.prototype.name = undefined; }npm install --save-dev babel-plugin-mark-fields// babel.config.json
{
"plugins": [
"babel-plugin-mark-fields",
["@babel/plugin-transform-class-properties", { "loose": false }]
]
}注意:
babel-plugin-mark-fields需在@babel/plugin-transform-class-properties之前执行,以确保在 class properties 被转换前先读取到字段信息。
mark-fields先运行,生成static { this.prototype.xxx = undefined }标记所有字段class-properties再运行,在 constructor 中用this.xxx = ...或Object.defineProperty赋实际值
这样在任何实例创建之前,Animal.prototype 上就已经有字段标记了,运行时代码可以提前做反射/校验。
| 类型 | 处理 |
|---|---|
普通字段 (name) |
✅ 标记 |
带初始值 (type = "dog") |
✅ 标记 |
| static 字段 | ❌ 跳过 |
private 字段 (#internal) |
❌ 跳过 |
computed key ([expr]) |
✅ 标记为 prototype[expr] |
| 带 decorator 的字段 | ✅ 标记 |
字符串 key ("my-field") |
✅ 标记为 prototype["my-field"] |
| 匿名 class expression | ✅ 支持 |
- 装饰器方案的补充:无论字段是否写了装饰器,插件都会补上 prototype 标记
- 运行时反射:框架需要在实例化之前知道类有哪些字段
- ORM / 序列化库:提前收集字段元数据