TypeScript嵌套对象getter中this指向错误,无法访问类属性
解决TypeScript中嵌套对象getter的this绑定问题
你碰到的是JavaScript/TypeScript中this绑定的典型场景,而且当前代码还藏着一个致命的无限递归坑——你在weekdays.monday的getter里写return this.monday,这里的this指向的是weekdays对象本身,所以会反复调用这个getter直到栈溢出。
为什么this指向不对?
在对象字面量的getter函数中,this默认绑定的是该对象字面量(也就是weekdays),而不是外层的DayOfWeekSelector类实例。所以它根本访问不到类里的actual私有属性。
解决方案
下面给你两种实用的修复方式,根据你的需求选择:
方案1:通过闭包捕获类实例的this(保留嵌套对象结构)
在类的构造函数里,用变量捕获类实例的this,然后在嵌套对象的getter/setter中使用这个变量访问actual属性:
class DayOfWeekSelector { private actual = { monday: false, tuesday: false, wednesday: false, thursday: false, friday: false, saturday: false, sunday: false }; public weekdays: { monday: boolean; tuesday: boolean; wednesday: boolean; thursday: boolean; friday: boolean; saturday: boolean; sunday: boolean; }; constructor() { // 捕获类实例的this,避免嵌套对象里的this指向错误 const classInstance = this; this.weekdays = { get monday() { return classInstance.actual.monday; }, set monday(value: boolean) { classInstance.actual.monday = value; }, get tuesday() { return classInstance.actual.tuesday; }, set tuesday(value: boolean) { classInstance.actual.tuesday = value; }, // 剩下的周几同理实现getter/setter get wednesday() { return classInstance.actual.wednesday; }, set wednesday(v: boolean) { classInstance.actual.wednesday = v; }, get thursday() { return classInstance.actual.thursday; }, set thursday(v: boolean) { classInstance.actual.thursday = v; }, get friday() { return classInstance.actual.friday; }, set friday(v: boolean) { classInstance.actual.friday = v; }, get saturday() { return classInstance.actual.saturday; }, set saturday(v: boolean) { classInstance.actual.saturday = v; }, get sunday() { return classInstance.actual.sunday; }, set sunday(v: boolean) { classInstance.actual.sunday = v; } }; } }
这样一来,嵌套对象里的getter就能正确访问到类的actual属性,同时避免了无限递归的问题。
方案2:直接使用类的getter/setter(简化结构)
如果不需要weekdays嵌套对象的结构,可以直接把周几的getter/setter定义在类上,这样this自然指向类实例:
class DayOfWeekSelector { private actual = { monday: false, tuesday: false, wednesday: false, thursday: false, friday: false, saturday: false, sunday: false }; get monday() { return this.actual.monday; } set monday(value: boolean) { this.actual.monday = value; } get tuesday() { return this.actual.tuesday; } set tuesday(value: boolean) { this.actual.tuesday = value; } // 其他周几同理实现getter/setter get wednesday() { return this.actual.wednesday; } set wednesday(v: boolean) { this.actual.wednesday = v; } get thursday() { return this.actual.thursday; } set thursday(v: boolean) { this.actual.thursday = v; } get friday() { return this.actual.friday; } set friday(v: boolean) { this.actual.friday = v; } get saturday() { return this.actual.saturday; } set saturday(v: boolean) { this.actual.saturday = v; } get sunday() { return this.actual.sunday; } set sunday(v: boolean) { this.actual.sunday = v; } }
这种写法更简洁,也符合TypeScript类的常规用法。
额外提醒
如果你的actual属性只是用来存储状态,也可以考虑用TypeScript的访问器直接封装,不需要额外的私有对象——不过如果有批量操作actual的需求,保留它也是合理的。
内容的提问来源于stack exchange,提问作者The DIMM Reaper
相关产品推荐
相关产品推荐

