JavaScript数组键赋值出现重复结果的原因排查
数组引用导致的异常行为解析
我不确定这是Bug还是自己忽略了某些细节。当前逻辑不够严谨,但发现以下代码存在异常行为:遍历data数组并创建与原数组值一致的新数组,预期结果应与原data数组匹配,但实际输出为[[ 'a', 'b', 'c', 'd' ], [ 'a', 'b', 'c', 'd' ]]。取消注释array1 = [];后,结果恢复为[[ 1, 2, 3, 4 ], [ 'a', 'b', 'c', 'd' ]]。想知道为何在i=1时,操作会影响array2[0]的值?
代码示例
let data = [ [1, 2, 3, 4], ['a', 'b', 'c', 'd'] ]; let array1 = [], array2 = []; for(let i = 0; i < data.length; i++) { let row = data[i]; //array1 = []; console.log(`Loop ${i}\n`); for(let j = 0; j < row.length; j++) { let value = data[i][j]; array1[j] = value; array2[i] = array1; console.log(`i: ${i}, j: ${j}`) console.log('array1', array1) console.log('array2', array2, "\n") } console.log(`----\n`); } console.log(array2)
问题原因解析
这是JavaScript引用类型的特性导致的,并非代码Bug:
- 数组属于引用类型,
array1在代码开头仅初始化一次,整个循环过程中始终指向同一个数组对象。 - 当i=0时,
array2[0]被赋值为array1的引用;到i=1时,修改的仍是同一个array1的内容,同时将该引用再次赋值给array2[1]。此时array2[0]和array2[1]指向的是同一个数组对象,所以当array1被i=1的循环修改为['a','b','c','d']后,array2的两个元素都会显示这个值。 - 取消注释
array1 = [];后,每次外层循环都会创建一个新的空数组,array1的引用会更新为这个新数组。i=0时array2[0]指向第一个新数组,i=1时array2[1]指向第二个新数组,两者互不干扰,结果自然符合预期。
如果要实现数组复制的需求,更简洁的方式可以使用数组的slice()方法或扩展运算符,比如array2[i] = [...row],直接创建原行的副本,无需嵌套循环。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

