new.target是判断构造函数是否被new调用的唯一可靠方式,它在new调用时指向当前构造函数,在普通调用时为undefined,且在继承中指向最外层被new的类。

在构造函数中,this 本身不能直接判断是否被 new 调用——它在非 new 调用时可能指向全局对象(非严格模式)或 undefined(严格模式),但这些行为不可靠、易受环境干扰。真正可靠且语义明确的判断方式是使用 new.target。
new.target 是判断 new 调用的权威依据
new.target 是 ES6 引入的元属性,在函数或构造方法内部可用:
- 通过
new调用时,new.target指向**当前正在执行的构造函数本身**(或子类构造函数); - 作为普通函数调用时,
new.target的值为undefined。
这比检查 this instanceof Constructor 或 this 是否为对象更底层、更确定——因为 instanceof 依赖原型链,而原型链可被篡改;this 的值则受严格模式、执行上下文等影响。
用 new.target 强制要求必须 new 调用
常见做法是在构造函数开头做守卫检查,阻止非法调用:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
function User(name) {
if (!new.target) {
throw new TypeError('User must be called with new');
}
this.name = name;
}
这样能确保:
-
new User('Alice')✅ 正常执行; -
User('Alice')❌ 抛出错误,不污染全局作用域; -
User.call({})或User.apply(globalThis)同样失败,因new.target仍为undefined。
在继承链中识别实际被 new 的类
当父类构造函数被子类 super() 触发时,new.target 不指向父类,而是指向**最外层被 new 的那个类**。这对设计可扩展基类很有用:
- 可在父类中记录日志:
console.log(`Instantiated as ${new.target.name}`); - 可做子类差异化初始化:
if (new.target === ChildA) { ... }; - 可拒绝父类被直接实例化:
if (new.target === Parent) throw new Error('Parent is abstract')。
注意 this 和 new.target 的配合边界
this 在构造函数中代表即将返回的实例对象,但它本身不携带“调用方式”信息;new.target 才是唯一可信的调用上下文标识。二者分工明确:
- 用
new.target做准入控制(是否 new、是否允许直接实例化); - 用
this做属性赋值、方法绑定、状态初始化; - 不要试图用
this.constructor === MyConstructor替代new.target—— 子类会覆盖constructor,导致误判。

















