React中二维数组fill创建后出现异常结果的原因排查
React井字棋棋盘组件问题解答
问题场景
组件接收moves属性(默认值为[[1,2]]),用于标记棋盘位置。通过let rows = Array(sideLength).fill(Array(sideLength).fill(''));初始化空白棋盘,再根据moves填充标记。预期第一个console.log输出全空的3x3数组,但实际和循环后的日志均显示每一行的第三列都是'X'。
问题解答
1. 第一个日志为何不是全空字符串?
Array.fill()填充引用类型(比如数组)时,会把同一个数组引用复制到每一个位置。也就是说,你初始化的rows数组里,三个元素指向的是同一个子数组。
另外,浏览器控制台的数组展示有延迟特性——它不会立刻快照数组状态,而是在你展开时显示当前最新状态。当你执行循环修改数组后,第一个console.log的内容已经被更新,所以你看到的不是初始化时的全空数组。
2. 循环后为何整列被填充而非仅[1,2]位置?
核心问题还是所有行共享同一个数组引用。你用Array(3).fill(Array(3).fill(''))创建的rows,本质是[共享数组, 共享数组, 共享数组]。
当你执行rows[1][2] = 'X'时,实际是修改了那个共享数组的第2个索引值,所以rows[0][2]、rows[1][2]、rows[2][2]都会同步变成'X',看起来就像整列被填充了。
修复方法
要创建独立的子数组,避免引用共享,可以用以下两种方式初始化棋盘:
// 方式1:使用Array.from生成独立子数组 let rows = Array.from({ length: sideLength }, () => Array(sideLength).fill('')); // 方式2:通过map生成独立子数组 let rows = Array(sideLength).fill(null).map(() => Array(sideLength).fill(''));
这样每个子数组都是独立的引用,修改某一行的某个位置不会影响其他行。
内容的提问来源于stack exchange,提问作者David J.
相关产品推荐
相关产品推荐

