使用展开语法复制数组后修改副本为何影响原数组?
问题原因:浅拷贝导致的引用共享
这个坑我刚学JS的时候也踩过!核心问题出在你用[...cities]做的是浅拷贝,并没有真正复制里面的子数组,导致你以为操作的是副本,其实还是在修改原数组的内容。
拆解细节:
- 当你执行
const citiesCopy = [...cities];时,JavaScript只会创建一个新的外层数组,但里面的每个子数组(比如['p','a','r','i','s'])并没有被复制——citiesCopy[0]和cities[0]指向的是同一个内存地址里的数组。你可以加一行console.log(cities[0] === citiesCopy[0])验证,结果会是true,说明它们是同一个引用。 - 接下来的
map方法遍历citiesCopy时,拿到的city参数就是原数组子数组的引用。所以你在forEach里修改city的元素(比如把a改成A),本质上就是在修改原数组cities里的对应子数组。
修复方案:
要避免修改原数组,你需要在map的时候先拷贝子数组,生成独立的副本再操作:
const cities = [ ['p','a','r','i','s'], ['n','e','w',' ','y','o','r','k'], ['s','a','n',' ','f','r','a','n','c','i','s','c','o'] ] const citiesCopy = [...cities]; const citiesWithUppercase = citiesCopy .map(city => { // 先拷贝子数组,得到独立的新数组 const cityCopy = [...city]; ['a', 's'].forEach((letter) => { const index = cityCopy.indexOf(letter); if (index !== -1) { cityCopy[index] = letter.toUpperCase(); } }) return cityCopy }) console.log("cities", cities); // 原数组保持小写,符合预期
这样操作的就是子数组的副本,原数组就不会被改动啦。
内容的提问来源于stack exchange,提问作者arnaudambro
相关产品推荐
相关产品推荐

