new.target 是 javascript 中用于检测函数或构造函数是否被 new 调用的只读属性;在 class 构造器中可判断调用方式、防止非法调用、支持继承区分、实现工厂逻辑,并比 instanceof 和 typeof 更早更可靠。

new.target 是 JavaScript 中一个只读属性,用于检测函数或构造函数是否被 new 关键字调用。在 class 语法中,它主要用于判断当前执行上下文是否处于实例化过程中,从而实现更安全、更可控的类行为。
防止类被直接调用(非 new 调用)
ES6 的 class 本质上是语法糖,但它的构造器不允许被当作普通函数调用——否则会抛出 TypeError。不过,有时你可能希望自定义这种限制逻辑,比如给出更友好的提示,或允许某些特殊调用方式。
利用 new.target 可以显式检查:如果为 undefined,说明没用 new;如果是当前类本身(即 new.target === MyClass),说明是正常实例化。
- 在构造函数中判断
if (!new.target),然后抛出自定义错误或做降级处理 - 注意:箭头函数没有
new.target,且不能作为构造器,所以只在 class 构造器或普通函数中可用 - 示例:
class Foo { constructor() { if (!new.target) throw new Error('Foo must be instantiated with new'); } }
支持继承时区分直接实例化与派生类调用
new.target 在继承链中指向**实际被 new 的那个类**,而不是声明构造器的类。这使得父类能感知自己是否被“直接”实例化,还是被子类间接调用。
- 若
new.target === MyClass,表示该类被直接new;若new.target !== MyClass(但仍是其子类),说明是子类在初始化 - 常用于禁止抽象基类被直接实例化:
if (new.target === BaseClass) throw new Error('BaseClass is abstract'); - 也可用于动态设置实例属性,例如根据调用者类型返回不同默认配置
配合工厂逻辑或可选构造模式
有些场景下你希望类既能被 new 使用,也能被当作工厂函数调用(比如返回缓存实例或代理对象)。new.target 提供了干净的分支依据。
- 构造器内通过
new.target分流:有值则走标准实例化流程;无值则执行工厂逻辑(如返回单例、从池中取实例等) - 需注意:此时类不能严格遵循“必须用 new”的语义,要确保文档和使用者明确约定调用方式
- 不推荐过度混用,但对兼容旧 API 或封装复杂初始化逻辑有一定价值
与 typeof 和 instanceof 的区别
new.target 检测的是**调用方式**,而非实例类型。它比 instanceof 更早介入(构造器执行时就可用),也比 typeof this === 'object' 更可靠(后者在严格模式下非 new 调用时 this 是 undefined)。
-
instanceof依赖原型链,在构造器内尚未完成原型绑定时可能不准 -
this在非 new 调用时可能是undefined(严格模式)或全局对象(非严格),不可靠 -
new.target是唯一能在构造器开头就明确反映“是否被 new”的原生机制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











