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

Chrome环境下JavaScript对象修改时出现诡异且不一致的异常

问题根源与修复方案

核心问题:浅拷贝导致的引用共享

你代码里用的{...boardMap}是浅拷贝——只复制了棋盘外层的a-h这些文件键,但每个键对应的内部rank对象(比如boardMap.a)还是和原boardMap共享引用。这意味着:

  • 当你在updateBoardMap里修改boardMapToUpdate[originFile][originRank]时,其实也在修改原boardMap里的对应位置
  • 浏览器环境中存在事件循环、异步渲染等因素,可能导致原boardMap被其他逻辑意外引用或修改,进而引发随机的棋盘异常;而Node环境是同步执行且测试用例隔离,所以没暴露这个问题

修复方案:改用深拷贝

需要确保棋盘的每一层对象都是全新的,彻底切断引用关联,有两种简单实现方式:

方式一:手动逐层拷贝

修改updateBoardMap中的拷贝逻辑,遍历每个file并拷贝其内部的rank对象:

export const updateBoardMap = (
  piece: string,
  origin: string,
  dest: string,
  boardMap: BoardType
): BoardType => {
  const [originFile, originRank, destFile, destRank] = getOriginAndDestInfo(origin, dest);

  // 深拷贝棋盘的每一层
  let boardMapToUpdate: BoardType = {};
  for (const file in boardMap) {
    boardMapToUpdate[file] = { ...boardMap[file] };
  }

  boardMapToUpdate[originFile][originRank] = '';
  boardMapToUpdate[destFile][destRank] = piece;

  return boardMapToUpdate;
};

方式二:使用structuredCloneAPI

利用浏览器和Node都支持的structuredClone做一键深拷贝,代码更简洁:

export const updateBoardMap = (
  piece: string,
  origin: string,
  dest: string,
  boardMap: BoardType
): BoardType => {
  const [originFile, originRank, destFile, destRank] = getOriginAndDestInfo(origin, dest);

  // 深拷贝整个棋盘对象
  let boardMapToUpdate: BoardType = structuredClone(boardMap);

  boardMapToUpdate[originFile][originRank] = '';
  boardMapToUpdate[destFile][destRank] = piece;

  return boardMapToUpdate;
};

额外优化

NewMove里的this.boardMap = { ...updatedBoardMap };是多余的,因为updateBoardMap已经返回了全新的对象,直接赋值即可:

private NewMove(): void {
    const updatedBoardMap = helpers.updateBoardMap(
      this.movingPiece,
      this.movingPiecesOrigin,
      this.movingPiecesDest,
      this.boardMap
    );
    
    this.boardMap = updatedBoardMap;
    
    this.whitesTurn = !this.whitesTurn;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:25:13