推荐使用 new.target 判断:ES6+ 中 new.target 在 new 调用时指向构造函数,普通调用时为 undefined;兼容方案可用 this instanceof MyFn 或 Object.getPrototypeOf(this) === MyFn.prototype。

JavaScript 中检测函数是否通过 new 调用,核心是区分两种执行上下文:普通调用(this 通常为 undefined 或全局对象)和构造调用(this 是新创建的实例,且原型链已绑定)。以下是几种可靠、实用的检测方式:
用 new.target 判断(推荐,ES6+)
new.target 是最直接、语义最清晰的方式。它在函数内部是一个元属性:通过 new 调用时指向当前构造函数;普通调用时为 undefined。
- 适用于普通函数和 class 构造器
- 子类继承中仍能准确反映“真正被 new 的那个类”,比如父类构造器里
new.target指向子类 - 无需依赖
this或原型链,无兼容性陷阱
示例:
function MyFn() {
if (!new.target) {
throw new Error('MyFn 必须用 new 调用');
}
console.log('正确:通过 new 执行');
}
// MyFn(); // 报错
// new MyFn(); // 正常用 instanceof 检查 this(ES5 兼容方案)
当函数被 new 调用时,this 是该函数的实例,因此 this instanceof MyFn 为 true;普通调用时,this 不是其实例(非严格模式下可能是全局对象,严格模式下为 undefined)。
- 需确保函数原型未被意外覆盖(否则
instanceof失效) - 在严格模式下更安全,避免
this指向全局对象造成误判 - 可配合
throw或自动补new(如某些兼容库做法)
示例:
function MyFn() {
'use strict';
if (!(this instanceof MyFn)) {
throw new Error('必须使用 new 调用');
}
// 初始化逻辑
}检查 this 的原型链(增强健壮性)
比 instanceof 更底层——直接对比 this 的原型是否等于函数的 prototype。因为 new 会把新对象的 [[Prototype]] 显式设为 MyFn.prototype。
- 可规避
instanceof在跨 iframe 或重写Symbol.hasInstance时的异常 - 需注意:若函数原型被替换(如
MyFn.prototype = {}),要同步修复constructor属性 - 通常与
instanceof配合使用,作为双重校验
示例:
function MyFn() {
if (Object.getPrototypeOf(this) !== MyFn.prototype) {
throw new Error('this 原型不匹配,禁止非 new 调用');
}
}结合严格模式 + this 类型判断(防御性写法)
在严格模式下,普通调用时 this 为 undefined,而 new 调用时 this 是对象。可直接用 typeof this === 'object' 辅助判断,但需注意 null 也是 'object',所以更稳妥的是:
- 先
'use strict' - 再检查
this != null && typeof this === 'object' && this.constructor === MyFn - 或更简洁地:仅靠
new.target已足够,此方式多用于需要兼容老环境且无法用new.target的场景











