安全构造函数需运行时校验:用 instanceof 自动补 new 防止 this 指向全局;new.target 严格拒绝非 new 调用;避免异步/副作用;可结合工厂函数统一管控。

编写安全的构造函数,核心是防止因漏写 new 导致 this 指向全局对象(如 window 或 globalThis),同时避免被恶意绕过或误用。这不是靠语法强制,而是靠运行时主动校验和防御性设计。
用 instanceof 检查并自动补 new
最常用、兼容性最好的方式:在构造函数开头判断 this 是否为当前类的实例,不是就主动用 new 调用自身并返回结果。
- 这样即使开发者忘记写
new,也能得到正确实例,不会污染全局 - 适用于所有环境(包括严格模式和非严格模式)
- 注意递归调用风险:必须确保条件分支明确,避免无限调用
示例:
function User(name) {if (!(this instanceof User)) {
return new User(name);
}
this.name = name;
}
配合 new.target 做更严格的限制
new.target 是 ES6 引入的元属性,只在通过 new 调用时有值(指向当前构造函数),直接调用时为 undefined。可用于拒绝非 new 调用。
- 适合需要强约束的场景(如库开发、内部 SDK)
- 比
instanceof更早介入,不依赖实例已存在 - 注意 IE 不支持,需考虑兼容性或搭配降级逻辑
示例:
function Admin(level) {if (!new.target) {
throw new Error('Admin must be called with new');
}
this.level = level;
}
避免 this 泄露和副作用
即使加了保护,构造函数内部仍可能因异步操作、回调或未绑定上下文导致 this 错乱或状态污染。
- 不在构造函数中直接执行异步逻辑(如
fetch、setTimeout),或确保回调内this正确绑定(用箭头函数或.bind(this)) - 避免在构造函数中修改全局变量、监听全局事件、挂载定时器等副作用操作
- 参数要做基础校验(如
name && typeof name === 'string'),防止传入无效值破坏实例结构
结合工厂函数做统一入口(进阶)
彻底隐藏构造函数,只暴露一个工厂函数,由它控制是否允许创建、如何初始化、是否复用等。
- 构造函数可设为模块私有(用闭包或 ES 模块作用域隔离)
- 工厂函数可加入权限检查、配置合并、缓存策略等逻辑
- 更适合复杂业务对象或需要生命周期管理的场景
示例:
const createService = (type) => {const constructors = { Http: HttpClient, WebSocket: WsClient };
if (!constructors[type]) throw new Error('Unknown service type');
return new constructors[type]();
};


















