高阶函数为何隐藏了我的ES6 Class属性?
嘿,我完全懂你碰到的这个问题——用高阶函数组合混入类的时候,只能拿到第一个继承类的属性,后面的混入属性得等实例化之后才能访问,对吧?结合你更新的截图来看,应该是在组合类的阶段就想访问后续混入的实例属性,这时候自然拿不到,因为这些属性还没被初始化呢。
先把你提到的高阶函数混入代码补全,方便咱们分析:
// 第一个混入:添加中间名 export const middleNameClass = middlename => BaseClass => { return class extends BaseClass { constructor(...args) { super(...args); // 实例属性,只有调用构造函数(实例化)时才会赋值 this.middleName = middlename; } }; }; // 第二个混入:添加姓氏 export const lastNameClass = lastname => BaseClass => { return class extends BaseClass { constructor(...args) { super(...args); this.lastName = lastname; } }; };
为什么会出现这个问题?
你现在的混入方式是每个高阶函数返回一个继承自BaseClass的新类,而混入的属性是在构造函数里赋值的实例属性。在组合类的阶段(也就是middleNameClass("xxx")(lastNameClass("yyy")(Base))这一步),这些类还只是类定义,并没有被实例化,构造函数也没执行,所以实例属性根本还没挂载到任何对象上。
至于你说的“只能访问第一个继承类的属性”,大概率是因为第一个继承的类如果是基础类(比如你自己定义的空类),它的属性可能是在类定义阶段就存在的(比如静态属性),而后续混入的都是实例属性,自然在组合阶段拿不到。
解决方案
根据你的需求,分两种情况处理:
1. 如果你需要在组合阶段访问属性(不需要实例化)
把属性改成静态属性,这样属性会挂载在类本身,而不是实例上,组合阶段就能直接访问:
export const middleNameClass = middlename => BaseClass => { return class extends BaseClass { // 静态属性,类定义阶段就存在 static middleName = middlename; constructor(...args) { super(...args); // 同时保留实例属性,方便实例使用 this.middleName = middlename; } }; }; // 组合时直接通过类访问静态属性 const CombinedClass = middleNameClass("James")(BaseClass); console.log(CombinedClass.middleName); // 输出 "James"
2. 如果你只需要在实例化后访问属性(常规场景)
这种情况其实是正常的,只要保证混入的顺序正确,让需要依赖其他属性的混入放在最后,这样在执行构造函数时,父类的属性已经被初始化了:
// 依赖其他属性的混入:生成全名 export const fullNameClass = BaseClass => { return class extends BaseClass { constructor(...args) { super(...args); // 此时super()已经执行了父类的构造函数,firstName/middleName/lastName都已存在 this.fullName = `${this.firstName} ${this.middleName} ${this.lastName}`; } }; }; // 组合顺序:基础类 → 姓氏混入 → 中间名混入 → 全名混入 const Person = fullNameClass( middleNameClass("James")( lastNameClass("Smith")( class { constructor(firstName) { this.firstName = firstName; } } ) ) ); const person = new Person("John"); console.log(person.fullName); // 输出 "John James Smith"
如果你的场景更复杂,比如需要在混入之间传递数据,还可以考虑把配置参数作为高阶函数的参数传递,而不是依赖实例属性。
内容的提问来源于stack exchange,提问作者Wilhelm
相关产品推荐
相关产品推荐

