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

开发国际象棋时array.push()未推入正确值,该如何解决?

问题描述

开发国际象棋程序时,尝试将伪合法着法(pseudo legal move)推入数组。推入前后打印pseudoLegalPos均显示正确,但打印目标数组时却发现内容错误,且最终推入的是本应在函数后续阶段才推入的值。

相关代码如下:

if (this.colour == 'white') {
         this.moveOffsets.yOffset = -1 * tileSize;
      }
      else {
         this.moveOffsets.yOffset = 1 * tileSize;
      }
      pseudoLegalPos.length = 0;
      pseudoLegalPos.push(this.x, this.y + this.moveOffsets.yOffset);
      console.log(pseudoLegalPos);
      this.pseudoLegal.push(pseudoLegalPos);
      console.log(pseudoLegalPos);
}
问题原因与解决方案

核心问题

你一直在复用同一个pseudoLegalPos数组对象。数组属于引用类型,每次调用this.pseudoLegal.push(pseudoLegalPos)时,并没有推入数组的副本,而是推入了该数组的内存引用。后续对pseudoLegalPos的修改(比如length = 0和新的push操作)会直接影响已经存入this.pseudoLegal里的引用,导致最终所有元素都指向最后一次修改后的数组。

修复方案

每次生成新的伪合法位置时,创建一个新数组,替代原有复用旧数组的逻辑:

if (this.colour == 'white') {
         this.moveOffsets.yOffset = -1 * tileSize;
      }
      else {
         this.moveOffsets.yOffset = 1 * tileSize;
      }
      // 每次创建新数组,避免引用复用
      const newPseudoLegalPos = [this.x, this.y + this.moveOffsets.yOffset];
      console.log(newPseudoLegalPos);
      this.pseudoLegal.push(newPseudoLegalPos);
      console.log(newPseudoLegalPos);
}

如果必须保留原变量名,也可以用slice()生成数组副本后推入:

// 偏移量设置代码不变
pseudoLegalPos.length = 0;
pseudoLegalPos.push(this.x, this.y + this.moveOffsets.yOffset);
console.log(pseudoLegalPos);
// 推入数组副本,而非原引用
this.pseudoLegal.push(pseudoLegalPos.slice());
console.log(pseudoLegalPos);
}

原理说明

JavaScript中,数组、对象这类引用类型存储的是内存地址。将数组推入另一个数组时,只是把这个地址存入目标数组,多个引用指向同一块内存空间。修改原数组时,所有指向它的引用都会同步看到变化。创建新数组或用slice()生成副本,就能避免这种共享内存导致的问题。

内容的提问来源于stack exchange,提问作者iamdeedz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:25:26