如何以纯函数方式在不修改初始数组的情况下,向嵌套数组内对象的数组添加元素?及代码异常原因排查
为什么扩展运算符拷贝数组后修改嵌套元素会影响原数组?如何用纯函数实现嵌套数组修改?
这是个很常见的JavaScript浅拷贝陷阱,我来给你拆解清楚:
问题根源:浅拷贝的引用共享
你用const newList = [...list]确实创建了一个新的外层数组,但这里的扩展运算符只做浅拷贝——它复制的是数组里每个元素的引用,而不是完整复制嵌套的对象/数组。
换句话说,newList里的第一个对象{ items: [...] }和原list里的第一个对象,指向的是内存里的同一个对象。所以当你执行newList[selectedList].items = [...list[selectedList].items, "4"]时,你其实是在修改那个共享的对象的items属性,原list自然也会跟着变化。
纯函数的解决方案:逐层创建新副本
要实现不修改原数组的纯函数式修改,你需要逐层复制要改动的部分,确保每一层都是新的引用:
方案1:使用map遍历数组
这种方式可读性强,适合需要条件修改的场景:
const list = [{ items: [ "2", "3", ], }, { items: [ "1", ], }, ]; const selectedList = 0; const newList = list.map((item, index) => { // 未选中的元素直接返回,不需要拷贝(因为我们不修改它们) if (index !== selectedList) return item; // 拷贝当前对象,同时生成新的items数组 return { ...item, items: [...item.items, "4"] }; }); console.log(list); // [ { items: [ '2', '3' ] }, { items: [ '1' ] } ] 原数组完好 console.log(newList); // [ { items: [ '2', '3', '4' ] }, { items: [ '1' ] } ] 新数组符合预期
方案2:直接切片拼接+对象拷贝
如果确定只修改指定位置的元素,这种写法更简洁:
const newList = [ // 复制选中位置之前的所有元素 ...list.slice(0, selectedList), // 拷贝目标对象并生成新的items数组 { ...list[selectedList], items: [...list[selectedList].items, "4"] }, // 复制选中位置之后的所有元素 ...list.slice(selectedList + 1) ];
这两种方法都遵循纯函数的原则:不修改输入的原始数据,只返回全新的结果,完美解决你的问题。
内容的提问来源于stack exchange,提问作者Lars Flieger
相关产品推荐
相关产品推荐

