为何用forEach修改过滤后的arr1会影响其他过滤数组?
为什么修改过滤后的数组元素会影响原数组和其他过滤数组?
嘿,这个问题其实是JavaScript里引用类型的经典陷阱!咱们一步步拆解原因:
首先要明确:JavaScript中的对象是引用类型,它们存储在堆内存里,而变量(包括数组元素)只是保存了指向这个堆内存地址的引用,不是对象本身的副本。
回到你的代码里:
- 当你执行
arr.filter(x => x)时,filter方法确实会创建一个新的数组,但这个新数组里的元素,只是把原数组arr中符合条件的对象的引用复制了过来——并没有克隆对象本身。 - 所以
res.arr1、res.arr2和原数组arr,这三个数组里的元素,其实都指向同一个堆内存中的对象。
这就解释了为什么你修改res.arr1里的对象属性后,arr和res.arr2里的对象也跟着变了:你根本不是在修改数组里的元素,而是在修改那个被所有数组共享的对象本身。不管通过哪个数组去访问这个对象,看到的都是修改后的状态。
怎么解决这个问题?
如果你希望每个数组里的对象都是独立的,不会互相影响,那你需要在过滤(或者映射)的时候,给每个对象创建一个副本。比如用浅拷贝的方式:
var arr = [{a: "one", b: "two"}]; var res = { arr1: arr.map(x => ({...x})), // 用扩展运算符浅拷贝对象 arr2: arr.map(x => ({...x})) }; res.arr1.forEach(x => x.a = "a"); console.log(arr); // 现在会打印 [{a: "one", b: "two"}] console.log(res.arr1); // 打印 [{a: "a", b: "two"}] console.log(res.arr2); // 打印 [{a: "one", b: "two"}]
如果你的对象是嵌套的复杂结构,那可能需要用深拷贝(比如递归拷贝、或者JSON.parse(JSON.stringify(x)),不过后者对函数、Symbol等类型有局限性)来确保所有层级的属性都是独立的。
内容的提问来源于stack exchange,提问作者Farhan Ghumra




