JS 中 map 和 forEach 的区别,很多地方都搞错了!

写 JS 代码用到的时候,以前我一般都用 for 或 for in ,少数情况下用 while ,后来 JS 的数组出了几个可用于循环的函数,但因为考虑兼容性问题,一开始我基本不用。 随着这些标准逐渐被支持,基本上不用考虑兼容性问题了,于是我就渐渐地试着用起这些函数来了。

用得最多的无疑是 map 和 forEach ,很多时候也只是需要循环一下,用哪个都差不多,于是看心情用 map 或 forEach ,但从函数名的长度来看,我当然会更倾向于使用 map 函数,但又因为写多了 PHP,习惯了 PHP 里的 foreach ,所以对 forEach 也有一定的好感。

不查资料我真的不知道这两个函数之间有什么区别,于是出于好奇,我还是去搜索了一下。

找到的结果基本都是这样的:

有些文章还给我举例来了:

说得头头是道,但这两个例子明显举得有问题,你发现了吗? 在用 forEach 的时候,是用:

 value.id = index+1

这明显修改了 value 的值

而用 map 的时候 却是:

return { ...value ,id:index+1}

这里并没有去修改原数组的元素。

如果用 map 的时候,也是:

 value.id = index+1

你看一下会不会修改到原数组?!

用 forEach:

var arr=[
    {
        id:1,
        name:"hi"
    },
    {
        id:2,
        name:"he"
    },
    {
        id:3,
        name:"hello"
    }
];
arr.forEach((v,i)=>{
    v.name="_"+v.name;
    v.age=i*10;
})
console.log(arr);
/*
[
  { id: 1, name: '_hi', age: 0 },
  { id: 2, name: '_he', age: 10 },
  { id: 3, name: '_hello', age: 20 }
]
*/

用 map:

var arr=[
    {
        id:1,
        name:"hi"
    },
    {
        id:2,
        name:"he"
    },
    {
        id:3,
        name:"hello"
    }
];
arr.map((v,i)=>{
    v.name="_"+v.name;
    v.age=i*10;
})
console.log(arr);
/*
[
  { id: 1, name: '_hi', age: 0 },
  { id: 2, name: '_he', age: 10 },
  { id: 3, name: '_hello', age: 20 }
]
*/

我们可以看到,使用 map 的时候,只要你在循环内修改了数组的元素,一样会影响到原数组,并不是很多地方说的 map 不会修改原数组。

当然,也有循环体内修改了元素,也不会对数组有影响的,比如:

var num=[1,2,3,4,5];
num.forEach((v,i)=>{
    v=v+i;
})
console.log(num);//[1,2,3,4,5]

var num2=[1,2,3,4,5];
num2.map((v,i)=>{
    v=v+i;
})
console.log(num2);//[1,2,3,4,5]

我们可以看到,尽管我在循环体内修改了元素:v=v+i;但原数据并没有被修改。

为什么呢? 其实有点 JS 常识的都应该知道,当数组的元素是对象时,就像我们把一个对象赋值给另一个变量,修改另一个变量是会影响到原变量的;而当一个变量是数字或字符串时则不会有影响。 所以,map 和 forEach 的区别根本和是否会修改到原数组没有关系。

它们最主要的区别是 map 有返回值,而 forEach 没有返回值。

我们再来看一段代码:

var num=[1,2,3,4,5];
var a=num.forEach((v,i)=>{
    return v+i; //其实这里用不用 return ,效果都一样
})
console.log(a);//undefined

var num2=[1,2,3,4,5];
var b=num2.map((v,i)=>{
    return v=v+i;
})
console.log(b);//[ 1, 3, 5, 7, 9 ]

所以,当我们只是需要一个循环,而不是需要通过一个数组去创建一个新的数组的时候,用 forEach 和 map 都可以,如果需要通过一个数组去创建一个新数组的话,用 map 。但需要注意的是,如果不想修改到原数组,当数组的元素是对象的时候,循环体内不要去修改它。 如果我们想通过修改旧数组得到一个新数组,但用 map 和 forEach 都可以。

但无论是 map 还是 forEach 在循环内都不能使用 break 或 return 去终于循环,如果你希望查找到某个元素后都退出循环的,那还是需要用回循环的语法,而不是数组迭代函数。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章