最准确、最推荐的方式是直接判断 new.target 是否存在且不为 undefined;它在 new 调用时指向被 new 的构造函数,普通调用时为 undefined,不依赖 this 绑定,ES6+ 环境稳定可靠。

直接看 new.target 是否存在且不为 undefined,是最准确、最推荐的方式。
new.target 是最可靠的判断依据
当函数通过 new 调用时,new.target 指向当前被 new 的构造函数;若作为普通函数调用(包括 call、apply、直接调用),new.target 的值就是 undefined。
- 它不依赖
this的绑定状态,不受严格模式或显式this绑定干扰 - 在类的
constructor和普通function中都原生支持 - ES6+ 环境下行为稳定,现代项目可放心使用
实际检测写法很简单
在函数体开头加一行判断即可:
if (!new.target) { throw new TypeError('请用 new 调用'); }- 不需要比较
new.target === MyConstructor(除非你想限制只能由特定类调用) - 箭头函数不能用
new,也不应作为构造函数,所以new.target不适用于它
它还能反映继承关系
在父类构造器中,new.target 指向的是**实际被 new 的子类**,而不是父类本身。这使得你可以:
- 阻止父类被直接实例化:
if (new.target === Parent) throw ... - 根据真实子类类型做差异化初始化
- 动态设置原型或属性,适配不同子类需求
兼容旧环境的注意点
如果必须支持 IE 等不支持 new.target 的浏览器,可退回到 this instanceof Constructor 判断,但该方式有缺陷:
- 在严格模式下,普通调用时
this是undefined,导致instanceof报错 - 若用
call(obj)显式传入对象,this instanceof Constructor可能误判为构造调用 - 因此,仅在必要时才用此降级方案

















