开发国际象棋时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
相关产品推荐
相关产品推荐

