将Ship对象嵌入其他对象返回后,getter为何失效?
问题原因与解决方案
问题根源
问题出在**扩展运算符(...)**上,和数组无关。
具体解释
Ship工厂返回的对象包含两个关键部分:
hitNumber是一个getter属性,依赖闭包中的_hitNumber变量返回当前值;hit函数负责修改闭包中的_hitNumber。
当你用...Ship(5)扩展对象时,JavaScript会执行以下操作:
- 遍历原Ship对象的可枚举属性,对于getter属性
hitNumber,会立即执行getter并将返回值(此时是0)作为普通静态值复制到新对象,而非保留getter本身; hit函数虽被复制到新对象,但它的闭包仍然指向原Ship对象创建时的_hitNumber变量。
这就导致:调用新对象的hit()时,原闭包的_hitNumber确实会递增,但新对象的hitNumber只是一个固定的0值,不是动态的getter,所以无法反映最新的_hitNumber。
解决方案
有两种简单的修复方式:
方案1:使用Object.assign合并对象
Object.assign会保留源对象的getter和setter属性,而非执行后复制静态值:
const Ship = (len) => { const length = len; let _hitNumber = 0; const hit = () => { _hitNumber = _hitNumber + 1; return _hitNumber; }; return { length, get hitNumber() { return _hitNumber; }, hit, }; }; const Fleet = () => { return [ Object.assign({ name: "Carrier" }, Ship(5)), Object.assign({ name: "Battleship" }, Ship(4)) ]; }; const testFleet = Fleet(); testFleet[0].hit(); console.log(testFleet[0].hitNumber); // 输出1,符合预期
方案2:让Ship工厂直接接收name参数
修改Ship工厂,直接返回包含name属性的对象,完全避免对象合并:
const Ship = (len, name) => { const length = len; let _hitNumber = 0; const hit = () => { _hitNumber += 1; return _hitNumber; }; return { name, length, get hitNumber() { return _hitNumber; }, hit, }; }; const Fleet = () => { return [ Ship(5, "Carrier"), Ship(4, "Battleship") ]; }; const testFleet = Fleet(); testFleet[0].hit(); console.log(testFleet[0].hitNumber); // 输出1,符合预期
内容的提问来源于stack exchange,提问作者Noah
相关产品推荐
相关产品推荐

