JavaScript中防止构造函数漏写new的方法有四种:一是函数内用this instanceof Constructor判断并自动补new;二是ES6类中用new.target检测并报错或修复;三是改用工厂函数彻底规避;四是配合TypeScript、ESLint等工具链提前拦截。

在 JavaScript 中,如果调用构造函数时忘了加 new,this 会指向全局对象(浏览器中是 window,Node.js 中是 global),导致意外的属性挂载和难以排查的 bug。防止漏掉 new 的核心思路是:在构造函数内部检测调用方式,并主动纠错或报错。
检查 this 是否为当前类的实例
最常用、兼容性最好的方法是在构造函数开头判断 this 是否是该构造函数的实例。如果不是,就手动用 new 重新调用一次:
function Person(name) {
if (!(this instanceof Person)) {
return new Person(name);
}
this.name = name;
}
// 两种调用都安全
const a = Person('Alice'); // 自动补 new
const b = new Person('Bob'); // 正常调用
console.log(a.name, b.name); // 'Alice' 'Bob'
这种方式对老式函数构造器友好,也适用于需要兼容 IE 的场景。
使用 ES6 类 + new.target(推荐现代写法)
ES6 引入了 new.target,它在通过 new 调用时指向当前构造函数,在普通调用时为 undefined。这是更语义化、更可靠的检测方式:
立即学习“Java免费学习笔记(深入)”;
class Person {
constructor(name) {
if (!new.target) {
throw new Error('Person must be called with new');
// 或 return new Person(name); 实现自动修复
}
this.name = name;
}
}
注意:new.target 在箭头函数、普通函数中不可用,只在 class 构造函数或 function 构造函数中有效。
用工厂函数替代构造函数(彻底规避问题)
如果不需要原型继承或强调面向对象,可直接改用工厂函数——它天然不依赖 new,语义清晰,且便于返回不同类型的实例:
function createPerson(name) {
return {
name,
greet() { return `Hello, ${this.name}`; }
};
}
const p = createPerson('Charlie'); // 不会出错,也不需要 new
搭配 Object.freeze() 还能进一步防止意外修改:
function createPerson(name) {
return Object.freeze({ name });
}
配合 TypeScript 或 ESLint 提前拦截
工具链层面也能辅助预防:
- TypeScript 编译器不会阻止漏
new,但可通过自定义类型(如声明构造签名 + 工厂签名)配合严格检查; - ESLint 插件
eslint-plugin-constructor-super或自定义规则可检测未用new调用已知构造函数的调用表达式; - JSDoc 标注
@constructor并配合 IDE 提示,也能增强开发时的提醒。
这类措施不能替代运行时防护,但能显著降低出错概率。


















