You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将Ship对象嵌入其他对象返回后,getter为何失效?

问题原因与解决方案

问题根源

问题出在**扩展运算符(...)**上,和数组无关。

具体解释

Ship工厂返回的对象包含两个关键部分:

  • hitNumber是一个getter属性,依赖闭包中的_hitNumber变量返回当前值;
  • hit函数负责修改闭包中的_hitNumber。

当你用...Ship(5)扩展对象时,JavaScript会执行以下操作:

  1. 遍历原Ship对象的可枚举属性,对于getter属性hitNumber,会立即执行getter并将返回值(此时是0)作为普通静态值复制到新对象,而非保留getter本身;
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 00:45:37