为何第一个JS函数操作复制数组会突变原数组,第二个却不会?
核心原理
JavaScript中的数组属于引用类型,变量存储的不是数组本身的内容,而是数组在堆内存中的存储地址,对数组的操作本质是通过地址访问到实际的数组对象再执行修改。
第一段函数原数组被突变的原因
你写的const copyArr = originalArr并没有生成新的数组副本,只是把原数组的内存地址赋值给了copyArr变量,此时copyArr和originalArr指向内存中的同一个数组对象。
而splice是JS内置的变异方法,会直接修改调用它的数组本身。你通过copyArr调用splice,本质就是修改两个变量共同指向的同一个数组,所以打印originalArr时自然会看到修改后的结果。
function removeSmallest(originalArr) { const copyArr = originalArr; // 仅赋值地址,未生成新数组 console.log(originalArr); copyArr.splice(copyArr.indexOf(Math.min(...copyArr)), 1); // 操作的是原数组本身 console.log(originalArr); // 原数组必然被修改 return copyArr; }
第二段函数原数组未被突变的原因
你先通过const copyArr = []创建了一个全新的、内存地址独立的空数组,再通过copyArr.push(...originalArr)把原数组的每一项逐个插入新数组,这一步完成了数组的浅拷贝,最终copyArr和originalArr是两个完全独立的数组对象,内存地址互不关联。
此时你对copyArr调用splice,修改的只是独立的新数组,完全不会影响到原数组,所以原数组不会发生突变。
function removeSmallest(originalArr) { const copyArr = []; copyArr.push(...originalArr); // 生成独立的新数组副本 console.log(originalArr); copyArr.splice(copyArr.indexOf(Math.min(...copyArr)), 1); // 仅修改新数组 console.log(originalArr); // 原数组不受影响 return copyArr; }
补充:常见的数组浅拷贝方式
除了push(...原数组)之外,以下写法也可以生成独立的数组副本,避免修改原数组:
- 展开运算符:
const copyArr = [...originalArr] - slice方法:
const copyArr = originalArr.slice() - Array.from方法:
const copyArr = Array.from(originalArr)
内容的提问来源于stack exchange,提问作者Natalia Grzywacz
相关产品推荐
相关产品推荐

