Javascript实现Builder模式时循环依赖引发的初始化错误如何解决?
问题原因
你的代码触发了ES模块的循环依赖问题,导入链路形成了闭环:PersonBuilder.js 导入了两个子Builder文件 PersonAgeBuilder.js、PersonAddressBuilder.js,而这两个子Builder文件又反过来导入了PersonBuilder.js。ES模块加载过程中,子Builder执行继承逻辑时,PersonBuilder 还未完成初始化,因此抛出引用错误。
同时你的代码存在两个隐性bug:
PersonBuilder构造函数中将实例赋值给了this.Person(大写P),但后续所有调用都用的是this.person(小写p),会导致person实例未定义PersonAgeBuilder的of方法没有返回this,会导致链式调用中断
解决方案
最推荐的方式是拆分公共基类打破循环依赖,步骤如下:
- 新建
PersonBuilderBase.js,抽取所有Builder的公共逻辑:
// PersonBuilderBase.js import Person from "./Person.js"; class PersonBuilderBase { constructor(person = new Person()) { this.person = person; } build() { return this.person; } } export default PersonBuilderBase;
- 修改两个子Builder文件,改为继承抽离的公共基类,不再导入原PersonBuilder:
// PersonAddressBuilder.js import PersonBuilderBase from "./PersonBuilderBase.js"; class PersonAddressBuilder extends PersonBuilderBase { constructor(person) { super(person); } in(city){ this.person.city = city; return this; } at(street) { this.person.street = street; return this; } } export default PersonAddressBuilder;
// PersonAgeBuilder.js import PersonBuilderBase from "./PersonBuilderBase.js"; class PersonAgeBuilder extends PersonBuilderBase { constructor(person) { super(person); } of(age){ this.person.age = age; return this; // 补充缺失的返回,保证链式调用可用 } } export default PersonAgeBuilder;
- 修改原
PersonBuilder.js,继承公共基类即可:
// PersonBuilder.js import PersonBuilderBase from "./PersonBuilderBase.js"; import PersonAgeBuilder from "./PersonAgeBuilder.js"; import PersonAddressBuilder from "./PersonAddressBuilder.js"; class PersonBuilder extends PersonBuilderBase { get lives() { return new PersonAddressBuilder(this.person); } get age() { return new PersonAgeBuilder(this.person); } } export default PersonBuilder;
如果你不想拆分文件,也可以将所有Builder类放到同一个文件中导出,直接消除跨文件循环导入的问题。
内容的提问来源于stack exchange,提问作者gyan mishra
相关产品推荐
相关产品推荐

