new.target 无法实现符合 gof 标准的抽象工厂模式,因其仅能检测调用方式、不支持产品族约束、无接口契约能力,本质是运行时控制而非编译期抽象;它适用于防直接实例化等底层构造控制场景。

new.target 不能用于实现符合国际标准的抽象工厂设计模式。
new.target 的真实作用范围
new.target 是一个元属性,仅在函数或构造函数内部可用,用于检测该函数是否被 new 调用,以及返回当前正在被实例化的构造函数本身。它不参与类型族管理、不支持多产品线协同创建、也不提供接口契约约束能力——而这三者正是抽象工厂模式(Abstract Factory Pattern)在《Design Patterns: Elements of Reusable Object-Oriented Software》中定义的核心特征:
- 封装一组相关或相互依赖的对象的创建逻辑
- 客户端通过抽象接口获取对象,完全不感知具体实现类
- 不同“产品族”(如 WinUIFactory / WebUIFactory)必须保证内部产品(Button + TextBox)版本一致、风格统一、行为兼容
为什么 new.target 不足以支撑抽象工厂
抽象工厂的本质是编译期契约 + 运行时多态绑定,而非运行时类型探测。常见误解是:用 new.target 判断调用者再分支返回不同实例,这实际仍是简单工厂的变体,且存在严重缺陷:
- 无法静态校验产品一致性(例如:WinButton 和 WinTextBox 是否配套)
- 强制运行时类型检查,破坏 TypeScript 类型系统和 IDE 补全
- 无法实现“工厂切换”而无需修改客户端代码(这是抽象工厂的关键价值)
- ES6 class 中 new.target 指向的是直接被 new 的类,不是父类或接口,无法表达“抽象工厂接口”的语义
真正合规的抽象工厂实现方式
要满足 GoF 标准,需明确分离三层结构,并由语言机制保障约束:
- 抽象工厂接口:用 abstract class 或 interface 声明 CreateButton()、CreateTextBox() 等方法
- 具体工厂实现:如 WinFactory extends AbstractFactory,每个方法返回对应 Win 系列的具体类
- 产品抽象层:IButton、ITextBox 接口,所有具体组件(WinButton、WebButton)必须实现
典型实现依赖 TypeScript 的 interface + class 继承 + 泛型约束,或 C# 的 abstract class + override,而非任何运行时元属性。
new.target 的合理使用场景
它适合解决以下问题,与抽象工厂无关:
- 防止类被直接调用(如
if (new.target === MyClass) throw new Error()) - 在基类构造器中区分是基类还是子类被 new(辅助实现受控继承)
- 配合 Reflect.construct 实现代理式实例化(如框架内部封装)
这些都属于底层构造控制,不构成“创建一族产品”的抽象能力。










