可通过 new.target 强制核心组件仅通过工厂方法实例化:若 new.target === MyClass 则抛错,禁止直接 new;子类继承允许,内部工厂用私有 token 绕过校验,配合 TypeScript 类型约束与运行时二次校验确保安全。

可以通过 new.target 在构造函数中判断调用上下文,强制核心组件仅允许通过指定工厂方法(如 getInstance())创建实例,禁止直接 new 调用。关键在于:若 new.target 指向类自身,说明被直接实例化,此时抛出错误。
在构造函数中拦截非法 new 调用
SDK 的核心类应将构造函数设为“受控入口”,不暴露公有构造逻辑:
- 构造函数内检查
new.target === MyClass,成立则抛出TypeError(表明有人直接new MyClass()) - 允许子类继承(如插件扩展),所以不能严格限制
new.target === void 0,而应只禁止顶层类直接实例化 - 保留私有构造标记(如 Symbol)或内部 flag 作为例外通道,供 SDK 自身的单例工厂安全调用
提供唯一受信的单例获取方式
对外只暴露静态方法(如 getInstance),该方法内部使用受信上下文创建实例:
- 用闭包变量缓存实例,首次调用时通过
new MyClass(INTERNAL_TOKEN)绕过拦截 - 构造函数识别传入的内部 token(如
Symbol('SDK_INTERNAL')),匹配则放行 - 确保 token 不可被外部访问或伪造(不暴露、不挂载到全局、不参与序列化)
配合 TypeScript 增强类型约束(可选但推荐)
虽 JS 运行时无法阻止 new,但可通过类型系统引导使用者:
- 将构造函数设为
private或protected,使 TS 编译阶段报错 - 声明类为
abstract,迫使用户只能调用静态工厂方法 - 导出类型时仅暴露实例类型(
MyClassInstance),而非构造函数类型
注意边界情况与防御措施
仅靠 new.target 不足以完全杜绝绕过,需组合防护:
- 避免依赖
arguments.callee或new.target.name—— 可被篡改或不可靠 - 在工厂方法中增加运行时校验(如
instance._isSDKInstance === true),防止手动 new 后赋值伪造 - 若 SDK 支持多环境(Web / Node / Worker),确保单例状态隔离,避免跨上下文污染

















