如何解决getter返回数组中对象属性修改失效的问题?
问题分析与解决方法
这个问题的核心原因很好找:你的names getter每次被调用时都会生成并返回一个全新的数组(以及数组里的每个对象)。
举个例子,当你执行data.names[1].name = "Yossi"时,你修改的只是这次data.names调用返回的临时数组里的临时对象。等下次再访问data.names,getter又会重新生成一组新的对象,所以控制台输出的还是原来的name2——你之前修改的那个对象早就被垃圾回收了。
而且你尝试给单个对象加的setter还犯了一个小错误:set name(newname) { this.name = newname; }这里会触发无限递归(给this.name赋值又会调用这个setter),就算解决了递归问题,也架不住getter每次都返回新对象,所以还是白搭。
下面给你两个可行的解决方案:
方案一:让getter返回同一个数组的引用
把数组存储为对象的内部变量,getter直接返回这个变量的引用,这样每次访问data.names都是同一个数组,修改里面的对象属性自然会生效:
var data = { // 用下划线开头表示这是内部私有变量(约定俗成) _names: [ { name: "name1" }, { name: "name2" }, { name: "name3" }, ], get names() { return this._names; } } data.names[1].name = "Yossi"; console.log(data.names[1]); // 现在会输出 { name: "Yossi" }
方案二:保护内部数组的同时支持修改
如果你想避免外部直接修改数组的结构(比如增删元素),可以让getter返回数组的浅拷贝,同时提供专门的修改方法来更新内部数据:
var data = { _names: [ { name: "name1" }, { name: "name2" }, { name: "name3" }, ], get names() { // 返回数组的浅拷贝,防止外部直接修改原数组的结构 return [...this._names]; }, // 提供修改指定索引对象name属性的方法 updateName(index, newName) { if (this._names[index]) { this._names[index].name = newName; } } } data.updateName(1, "Yossi"); console.log(data.names[1]); // 输出 { name: "Yossi" }
内容的提问来源于stack exchange,提问作者Yuval A.
相关产品推荐
相关产品推荐

