new.target 可可靠检测构造调用上下文,替代脆弱的 this.constructor 判断,结合原型链扫描可校验抽象方法实现,实现平滑迁移且兼容旧继承链。

new.target 不能直接实现抽象类,但它能可靠检测构造调用上下文——这是重构遗留系统中“伪抽象类”的关键突破口。
识别遗留系统中的抽象类伪装模式
老代码常通过抛错或空实现模拟抽象类,例如:
function Animal() {
if (this.constructor === Animal) {
throw new Error('Animal 是抽象类,不可直接实例化');
}
}
Animal.prototype.speak = function() {
throw new Error('子类必须重写 speak 方法');
};
这类逻辑脆弱:依赖 this.constructor(易被篡改)、无法阻止原型链调用、对箭头函数或 bind 场景失效。
用 new.target 替换 this.constructor 判断
new.target 指向当前 new 表达式调用的目标构造器,且不可被覆盖,更健壮:
- 在构造函数首行检查
if (new.target === Animal) { throw ... } - 它不依赖
this状态,即使构造函数被call/apply调用(非 new)时new.target为undefined,可一并拦截 - 配合
Object.is()比较,避免引用误判
约束抽象方法的运行时校验
new.target 本身不检查方法是否被重写,但可与原型链扫描结合:
- 在基类构造函数中,遍历
Object.getOwnPropertyNames(new.target.prototype) - 对比基类原型上标记为“必须实现”的方法名(如用 Symbol 或约定前缀
_abstract_) - 若子类原型未提供该方法实现(且不是继承自基类),则报错
示例片段:
function Shape() {
if (new.target === Shape) {
throw new Error('Shape 是抽象类');
}
const required = ['area', 'perimeter'];
for (const method of required) {
const desc = Object.getOwnPropertyDescriptor(new.target.prototype, method);
if (!desc || desc.value === Shape.prototype[method]) {
throw new Error(`子类必须实现 ${method} 方法`);
}
}
}
平滑迁移:兼容旧继承链与工具链
重构时避免破坏现有 instanceof 或序列化逻辑:
- 保持原型链结构不变(
Child.prototype.__proto__ === Parent.prototype) - 不替换原有构造函数名,仅增强其内部校验逻辑
- 若系统依赖 Babel 等转译,确认目标环境支持
new.target(ES6+,Node.js ≥ 4,现代浏览器均支持) - 对需兼容旧引擎的场景,可用简单 UA 检测 + 降级回
this.constructor方案(仅作兜底)










