复制数组元素修改后添加引发rank值异常问题咨询
问题排查与解决方案
嘿,我来帮你揪出这个问题的根源!
核心问题出在浅拷贝导致的对象引用共享:你用newData.slice()配合concat复制数组的方式,只做了浅拷贝——数组里的元素是对象,浅拷贝只会复制对象的引用,不会创建新的独立对象实例。所以setData里的两个元素其实指向的是同一个原始对象,你修改其中一个的key2.rank,另一个自然也会跟着变,本质上你是在同一个对象上修改了两次rank,最后两条记录的Rank当然都是1。
咱们拆解下你的代码逻辑:
newData = [{...}]:创建了一个包含一个对象的数组。newData.concat(newData.slice()):slice()返回原数组的浅拷贝,concat把原数组和这个浅拷贝合并,得到的setData其实是[原对象, 原对象]——两个元素是同一个对象的引用。forEach循环里修改data.key2.rank =+1:第一次修改把原对象的rank改成1,第二次还是修改同一个对象的rank,结果两条记录都显示1。
解决办法:实现对象层级的深拷贝
你需要真正复制数组里的对象,而不是复制引用。这里有几种简单的实现方式:
方式1:直接创建新对象(最直观,适合你的场景)
let newData = [{ "key1": { "cc":'IND' }, "key2": { "rank": null } }]; // 直接基于原对象创建新的独立对象,并设置rank为1 let setData = [ ...newData, { ...newData[0], key2: { ...newData[0].key2, rank: 1 } } ];
方式2:用map批量复制(适合需要批量处理的场景)
let newData = [{ "key1": { "cc":'IND' }, "key2": { "rank": null } }]; let setData = newData.concat( newData.map(item => ({ ...item, key2: { ...item.key2, rank: 1 } })) );
方式3:JSON序列化反序列化(适合嵌套层级较深的对象)
注意:这种方式不适合包含函数、Symbol等特殊类型的对象,但你的场景完全适用:
let newData = [{ "key1": { "cc":'IND' }, "key2": { "rank": null } }]; let setData = newData.concat( JSON.parse(JSON.stringify(newData)).map(item => { item.key2.rank = 1; return item; }) );
这样修改后,setData里的两个对象是完全独立的,第一条记录的rank保持null,第二条的rank是1,完美符合你的预期。
内容的提问来源于stack exchange,提问作者Arun K
相关产品推荐
相关产品推荐

