JS动态创建嵌套对象getter访问器时如何引用父对象属性
问题:JS嵌套对象的getter如何访问父级作用域属性
我不确定该如何清晰表述该问题,以下代码片段可直观展示我的开发场景:我定义了如下JS类:
// This is my current Implementation of code Class OptionCls { Constructor(){ this.dataObj = { name: '', selectedValue: '', options: [], } } setOptions(optionArray){ this.dataObj.options = this.prepareOptions(optionArray); } prepareOptions(options){ for(let obj of options){ obj.label = obj.label ? obj.label : ''; obj.value = obj.value ? obj.value : ''; // automated properties for dropdown options Object.defineProperty(obj, '_id', { value: uniqueId() }); } return options; } // class end }
我调用setOptions()方法并传入对象数组,为dataObj.options属性赋值。
目前我需要在dataObj.options的每个子项上定义名为selected的getter访问器属性,该属性需要自动读取父级属性dataObj.selectedValue,基于该值判断当前选项是否为选中状态,我初步的实现思路如下:
prepareOptions(options){ for(let obj of options){ obj.label = obj.label ? obj.label : ''; obj.value = obj.value ? obj.value : ''; // automated properties for dropdown options Object.defineProperty(obj, '_id', { value: uniqueId() }); Object.defineProperty(obj, 'selected', { get(){ return this.dataObj.selectedValue.split(',').includes(this.value); // Now over here `this` will be refer to local this scope not the parent object } }); } return options; }
最终dataObj的输出结构需要符合如下预期:
{ name: '', selectedValue: 'us,uk', options: [ { _id: "13", label: "United States", value: "us", selected: true }, { _id: "11", label: "Australia", value: "au", selected: false }, { _id: "10", label: "United Kingdom", value: "uk", selected: true } ] }
上述实现的问题:getter函数内部的this指向当前嵌套的选项对象本身,无法引用父对象的selectedValue属性。
解决方案
问题本质是JS的this绑定规则:对象方法/getter执行时,this默认指向当前挂载该方法的对象,也就是单个选项实例,自然拿不到外层类实例上的dataObj。直接用闭包捕获外层作用域的dataObj引用即可,不需要给选项对象加反向父级引用这类冗余设计。
修正后的prepareOptions代码如下:
prepareOptions(options){ // 提前捕获父级dataObj的引用,供内部getter闭包访问 const parentData = this.dataObj; for(let obj of options){ obj.label = obj.label || ''; obj.value = obj.value || ''; // 注意加enumerable: true,否则属性默认不可枚举,打印/序列化时看不到 Object.defineProperty(obj, '_id', { value: uniqueId(), enumerable: true }); Object.defineProperty(obj, 'selected', { enumerable: true, get(){ // 加空值兜底,避免selectedValue为空时split抛错 const selectedList = parentData.selectedValue ? parentData.selectedValue.split(',') : []; return selectedList.includes(this.value); } }); } return options; }
实现说明
- 闭包捕获的
parentData是对dataObj的直接引用,后续修改dataObj.selectedValue时,所有选项的selected状态会自动实时计算,不需要手动遍历更新选项状态。 - 补充
enumerable: true配置:Object.defineProperty定义的属性默认不可枚举,不加这个配置的话,打印对象、调用JSON.stringify序列化时都看不到_id和selected属性,和预期输出结构不符。 - 增加空值兜底:当
selectedValue为空字符串、null或undefined时,直接返回空数组做匹配,不会触发split方法的类型报错。 - 不需要在选项对象上额外存储父级引用,不会污染选项的原始数据结构。
内容的提问来源于stack exchange,提问作者user2809299
相关产品推荐
相关产品推荐

