只读属性描述符(writable: false)不实现智能装配或流式构建,仅保障装配后依赖字段的不可变性与契约稳定性;它需配合类设计、元编程、依赖注入容器和工厂函数共同完成自动装配与流式构建。

只读属性描述符本身不能直接实现“智能流式工厂模式”或“自动装配依赖”,它只是 JavaScript 中控制属性行为的一种底层机制。真正的智能装配和流式构建,需要结合类设计、元编程(如装饰器或 Reflect)、依赖注入容器以及工厂函数共同完成。只读描述符(writable: false)在此过程中的作用,是**保障装配结果的不可变性与契约稳定性**——即一旦依赖被注入或实例被构建完成,关键字段不应被意外篡改。
用 Object.defineProperty 锁定已装配的依赖
在工厂返回实例前,可将已解析的依赖通过只读属性描述符挂载到实例上,防止运行时误写:
function createServiceInstance(ctor, container) {
const instance = new ctor();
const deps = Reflect.getMetadata('design:paramtypes', ctor) || [];
deps.forEach((depType, i) => {
const dep = container.resolve(depType);
Object.defineProperty(instance, `__dep_${i}`, {
value: dep,
writable: false, // ← 关键:禁止重赋值
enumerable: false,
configurable: false
});
});
return instance;
}
这样,消费者代码无法通过 instance.__dep_0 = ... 篡改依赖,但可通过方法访问(如封装 getter),保持接口清晰。
配合装饰器 + 元数据实现子类自动识别
所谓“根据子类自动装配”,本质是运行时识别继承链并提取元信息。可用装饰器标记可装配类,并在工厂中递归查找:
- 用
@injectable()装饰基类或子类,注册其构造器与依赖元数据 - 工厂接收子类构造器(如
MyApiService),检查ctor.superClass或自定义@@factoryKey标识 - 按需合并父类声明的依赖项(例如父类
BaseClient需要HttpClient,子类额外需要AuthStore)
流式构建的关键在于返回可链式调用的 Builder 对象
真正的“流式”不是靠只读属性,而是靠 builder 模式返回自身(return this),并在最终 .build() 时触发装配逻辑:
class ServiceBuilder {
constructor(ctor) {
this.ctor = ctor;
this.overrides = new Map();
}
with(depType, instance) {
this.overrides.set(depType, instance);
return this; // ← 流式基础
}
build(container = defaultContainer) {
const resolvedDeps = Reflect.getMetadata('design:paramtypes', this.ctor)
.map(type => this.overrides.get(type) ?? container.resolve(type));
const instance = new this.ctor(...resolvedDeps);
// 此处锁定所有注入字段
resolvedDeps.forEach((dep, i) => {
Object.defineProperty(instance, `_dep_${i}`, {
value: dep,
writable: false,
enumerable: false
});
});
return instance;
}
}
// 使用
const svc = new ServiceBuilder(MyApiService)
.with(HttpClient, mockClient)
.build(testContainer);
注意事项:只读 ≠ 不可访问,也不解决循环依赖
只读描述符仅阻止赋值,不隐藏属性、不防删除(configurable: false 才防删)、不参与依赖图分析。若需真正健壮的自动装配,仍需:
- 容器支持作用域(request/scoped/singleton)和生命周期钩子
- 静态分析或运行时反射补全缺失的
design:paramtypes(尤其 TypeScript 编译后需启用emitDecoratorMetadata) - 避免在只读字段上做响应式代理(如 Vue/React 的响应式系统可能绕过
writable: false)
只读属性描述符是加固环节,不是驱动环节。智能装配靠元数据与容器,流式体验靠 builder 返回自身,而只读性则是交付那一刻对契约的郑重承诺。

















