为什么说在forEach中不要使用item修改原数据?

65 阅读1分钟

问题:

是不是很多前端小白遇到过下面这种情况,同样是item,为什么一个能修改原数据,但另一个就不能呢。看完讲解绝对让你透彻。

let arr = [1, 2, 3];
arr.forEach((item, index) => {
  item = item * 2;
});
console.log(arr); // 输出:[1, 2, 3]
let arr = [{name: 'Alice'}, {name: 'Bob'}];
arr.forEach(item => {
  item.name = 'Changed';
});
console.log(arr); // 输出:[{name: 'Changed'}, {name: 'Changed'}]

开始讲解

我们先回想一下js中基本数据类型和引用数据类型的赋值。
  1. 基本数据类型在赋值时是值传递,不会改变原数据,如下
    let a = 1
    let b = a
    b = 2
    console.log(a) // 1
    console.log(b) // 2
    
  2. 引用数据类型在赋值时是引用传递,也可以叫内存地址传递,如下例子,假如a对象的内存地址是0x11,那么在 let b = a 的时候其实是将a所对应的内存地址0x11给了b,所以这样会改变原数据(栈内存和堆内存属于基础,不了解的同学去自行了解)
    let a = {
        x: 1
    }
    let b = a
    b.x = 2
    console.log(a.x) // 1
    console.log(b.x) // 1
    
有了上面的例子理解起来就简单多了,在forEach循环中,你会使用回调函数的第一个参数item来访问数组的元素。这个item是数组元素的一个副本(这个副本的意思就是上面基本数据或者引用数据的赋值),这就是上面问题的答案!