JS forEach遍历数组时修改对象属性生效、重赋值对象失效原因
forEach遍历对象数组时属性修改生效、整体赋值不生效的原因
核心是JavaScript的值传递规则,以及forEach回调参数的本质:
数组里存储的引用类型(比如对象),实际存的是对象在堆内存中的引用地址。forEach执行时,回调函数拿到的item参数,是对数组当前位置存储值的一份拷贝——也就是拷贝了这份引用地址。
两种修改方式的差异:
- 修改对象属性:
item拷贝的地址和数组对应位置存的地址,指向堆内存里的同一个对象。通过这个地址修改对象的属性,是直接改动堆内存中原对象的内容,数组存储的地址没有发生变化,所以修改能被感知到,生效。 - 给
item整体赋新对象:这一步只是把回调函数内的局部变量item存储的地址改成了新对象的地址,数组对应位置存的原引用地址完全没有被改动,依旧指向原来的对象。等回调函数执行完毕,局部变量item会被销毁,新对象没有被存入数组,自然不会生效。
复现代码
const arr1 = [ { id: 1, value: 1 }, { id: 2, value: 2 }, { id: 3, value: 3 }, { id: 4, value: 4 }, { id: 5, value: 5 }, ] arr1.forEach((item, index) => { if (item.id === 1) { item.value *= 10 // 修改对象属性,生效 } }); console.log(arr1); arr1.forEach((item, index) => { if (item.id === 1) { item = {id:6,value:6} // 给局部变量item重新赋值,不生效 } }); console.log(arr1);
如果需要替换数组里的整个对象元素,不能直接给item赋值,要通过索引直接操作原数组:
arr1.forEach((item, index) => { if (item.id === 1) { arr1[index] = {id:6,value:6} // 直接修改数组对应位置的值,生效 } });
内容的提问来源于stack exchange,提问作者Jim K
相关产品推荐
相关产品推荐

