new.target 是 ES6 引入的元属性,用于可靠判断函数是否通过 new 调用:new 调用时指向当前构造函数,否则为 undefined;支持继承中识别真实构造类,可防止非 new 调用并实现差异化初始化。

new.target 是 ES6 引入的元属性,用于在函数或构造函数内部检测是否通过 new 关键字调用。它不是变量,不能被赋值或删除,只在函数执行时动态存在——当函数被 new 调用时,new.target 指向当前构造函数;否则为 undefined。这是目前最可靠、原生支持的判断实例化调用的方式。
区分普通调用与构造调用
传统上有人用 this instanceof arguments.callee 或检查 this 是否为新对象来判断,但这些方法不可靠(如箭头函数无 arguments,严格模式下 arguments.callee 禁用,且 this 可能被显式绑定)。而 new.target 直接反映调用方式:
- 函数体中
if (new.target === undefined)→ 普通调用(包括箭头函数、普通函数调用) -
if (new.target === MyConstructor)→ 明确由new MyConstructor()实例化 - 子类构造器中
new.target指向**实际被new的类**,而非父类,可用于实现“禁止直接实例化父类”逻辑
防止非 new 调用的构造函数
很多构造函数设计上只应通过 new 使用(如 Array、Date 在非 new 下行为异常)。可用 new.target 主动拦截:
function Person(name) {
if (!new.target) {
throw new TypeError('Person must be called with new');
}
this.name = name;
}
这样 Person('Alice') 报错,new Person('Alice') 正常。比依赖 this 是否为实例更健壮——即使 this 被 call 绑定为对象,只要没用 new,new.target 仍为 undefined。
在继承链中识别真实构造者
子类继承父类时,父类构造器中的 new.target 不是父类本身,而是最终被 new 的那个类。这可用于定制初始化逻辑:
class Animal {
constructor(name) {
console.log('new.target:', new.target.name); // 输出 'Dog' 或 'Animal'
this.name = name;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
}
new Dog('Leo', 'Golden'); // new.target 在 Animal 构造器中是 Dog
利用这点可实现:父类仅允许被继承、不允许直接 new Animal()(检查 new.target === Animal 则抛错),或根据真实子类类型做差异化初始化。
注意边界情况和兼容性
new.target 在普通函数、箭头函数、类方法、getter/setter 中均可访问,但在以下情况无意义或受限:
- 全局作用域或模块顶层:语法错误,
new.target只能在函数内使用 - ES5 环境不支持:需 Babel 转译(但转译无法完全模拟语义,建议现代环境直接使用)
- 严格模式与非严格模式均有效,无差异
- 异步函数、生成器函数中同样可用,逻辑一致
不复杂但容易忽略。

















