new.target 可实现运行时抽象类,禁止直接实例化:若 new.target === 当前类则抛错,否则允许子类继承初始化;它指向最底层被 new 的构造函数,支持多层抽象校验,与 typescript abstract 互补增强约束。

new.target 是 JavaScript 中用于检测函数或构造函数是否被 new 调用的关键属性。在框架设计中,它能有效辅助实现“运行时抽象类”——即禁止直接实例化、只允许被继承的类。这虽不能像 TypeScript 那样提供编译期检查,但可在运行时拦截非法调用,提升框架健壮性与 API 约束力。
用 new.target 拦截直接实例化
抽象类的核心语义是“不可被直接 new”,只供子类 extends。利用 new.target 可在构造函数中判断当前调用上下文:
- 若
new.target === 当前类,说明正被直接实例化,应抛出错误; - 若
new.target !== 当前类(通常是子类),则允许执行初始化逻辑。
示例:
class AbstractComponent {constructor() {
if (new.target === AbstractComponent) {
throw new TypeError('AbstractComponent cannot be instantiated directly');
}
// 子类可安全执行的公共初始化逻辑
this.id = Date.now();
}
}
class Button extends AbstractComponent {
constructor(label) {
super(); // 此时 new.target 是 Button,不报错
this.label = label;
}
}
// ✅ 正确
new Button('Submit');
// ❌ 报错:TypeError: AbstractComponent cannot be instantiated directly
new AbstractComponent();
配合静态方法与模板方法模式
抽象类常定义骨架流程(模板方法),将具体步骤延迟到子类实现。结合 new.target 可确保骨架逻辑仅在合法继承链中运行:
- 在构造函数中用
new.target做准入校验; - 定义
render()、mount()等抽象方法(无实现或 throw); - 提供
init()等模板方法,内部调用抽象方法,由子类实现细节。
这样既保持接口契约,又避免子类遗漏关键覆写。
注意继承链中的 new.target 行为
new.target 始终指向**最底层被 new 的构造函数**,而非当前执行的 class。这意味着:
- 即使在父类构造函数里访问
new.target,它也反映最终实例化的类; - 可用于多层抽象(如
Base → AbstractView → ListView),只需在最顶层抽象基类中校验new.target === Base即可; - 若允许多级抽象(如只禁止某一层直接实例化),需明确比较目标类引用,而非简单判断是否相等。
与 TypeScript abstract class 的互补关系
JS 运行时无法真正声明 abstract 类型,new.target 是轻量可靠的补充手段:
- TypeScript 编译期检查抽象方法是否被实现,但生成 JS 后仍可绕过;
-
new.target在运行时堵住直接new的漏洞,二者叠加形成完整约束; - 框架文档和类型定义中可明确标注“此为抽象基类”,配合运行时防护,降低误用风险。
不复杂但容易忽略。











