JS中find获取元素后复制,map修改仍影响原数组如何解决?
问题根源:浅拷贝的引用共享问题
你遇到的问题核心在于**Object.assign({}, a)是浅拷贝**——它只会复制a的顶层属性,但对于a.children这种引用类型(数组),拷贝的只是它的引用,而不是整个数组及其内部元素的独立副本。这就意味着b.children和原数组里的a.children指向的是同一个内存地址,你在map里修改b.children的元素时,实际上还是在修改原数组里的对应元素。
解决方案:深拷贝目标对象的所有层级
要让map只修改复制后的对象b,我们需要确保b的children数组以及数组内的每个元素都是原数据的独立副本,彻底切断引用共享。下面提供几种原生实现方案:
方案1:逐层手动深拷贝(适合结构简单的对象)
如果你的children元素都是简单对象(没有深层嵌套),可以用扩展运算符结合map来逐层拷贝:
// 找到目标元素 let a = this.menu.getMenuItems().find((item) => item.$entityType === val); // 拷贝顶层属性 + 深拷贝children数组的每个元素 let b = { ...a, children: a.children.map(child => ({ ...child })) // 对每个child做浅拷贝,避免引用共享 }; // 现在修改b.children的元素不会影响原数组 this.dictChildren = b.children.map((item) => { // 这里可以安全修改item的属性,比如: // item.label = item.label + ' (copied)'; return item; });
方案2:JSON序列化深拷贝(适合无特殊类型的对象)
如果你的对象结构比较复杂(有多层嵌套),但没有函数、Symbol、循环引用这类无法被JSON序列化的类型,可以用JSON.parse(JSON.stringify())实现一键深拷贝:
let a = this.menu.getMenuItems().find((item) => item.$entityType === val); // 深拷贝整个对象,包括所有嵌套层级 let b = JSON.parse(JSON.stringify(a)); // 此时b和原对象完全独立,修改b的任何属性都不会影响原数组 this.dictChildren = b.children.map((item) => { // 放心修改item return item; });
⚠️ 注意:这个方法的局限性是会丢失函数、Symbol、undefined等JSON不支持的类型,如果你的对象包含这些,不要用这个方法。
方案3:递归深拷贝函数(自定义实现,最灵活)
如果需要处理特殊类型的对象,可以自己写一个递归深拷贝函数:
function deepCopy(obj) { if (obj === null || typeof obj !== 'object') return obj; // 处理数组 if (Array.isArray(obj)) return obj.map(item => deepCopy(item)); // 处理对象 const copiedObj = {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { copiedObj[key] = deepCopy(obj[key]); } } return copiedObj; } // 使用方式 let a = this.menu.getMenuItems().find((item) => item.$entityType === val); let b = deepCopy(a); this.dictChildren = b.children.map((item) => { // 修改item return item; });
总结
核心就是要确保你复制出来的b及其内部的所有引用类型属性都和原对象完全独立,避免共享内存地址。根据你的对象结构选择合适的深拷贝方式即可。
内容的提问来源于stack exchange,提问作者POV
相关产品推荐
相关产品推荐

