寫 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 去終於循環,如果你希望查找到某個元素後都退出循環的,那還是需要用回循環的語法,而不是數組迭代函數。