微信二維碼烏魯木齊seo
前端面試題庫 (面試必備)?? ? ? ? ? ?推薦:★★★★★
地址:前端面試題庫
【國慶頭像】- 國慶愛國 程序員頭像!總有一款適合你!
前言
為什么要寫這么一篇文章,原因是今天下午水群的時候,有個小伙伴分享自己的面試題,其中一個是foreach
和map
的區(qū)別,其實是蠻簡單,蠻基礎(chǔ)的一道題,但是他是這么回答的
一個會改變原數(shù)組,一個不會
我當場就懵了,我以為是整活,誰知道是認真的,并且給我發(fā)了一篇文章
我看完更蚌埠住了,那么多對的文章,你偏偏挑個錯的
然后我發(fā)現(xiàn),真的很多人都這么認為的,那這真的是一件很可怕的事情,明明你自己試一下就知道了,甚至有不少文章都是這么寫的,但是我也看到了不錯的文章,寫的已經(jīng)不錯了
那么咱們,就這個簡單的問題,咱們淺淺地說一下~
區(qū)別
map
會返回一個新的數(shù)組,而forEach
不會
簡單的區(qū)別我們可以在MDN
上看看
簡單來說什么意思,map
會返回一個新的數(shù)組,而forEach
不會,實際上是因為forEach
不會返回任何值(實際上返回的是undefined
),而map
?是有返回值的,是一個新數(shù)組
我們可以簡單手寫一下,看的會更直觀一些
map
function myMap(array, callback) {const result = [];for (let i = 0; i < array.length; i++) {result.push(callback(array[i], i, array));}return result;
}
forEach
function myForEach(array, callback) {for (let i = 0; i < array.length; i++) {callback(array[i], i, array);}
}
再簡單點對比
forEach
?和?map
?的實現(xiàn)原理相似。它們都是通過遍歷數(shù)組,對數(shù)組的每個元素執(zhí)行特定的函數(shù)。區(qū)別主要在于它們處理函數(shù)返回值的方式不同。forEach
?忽略函數(shù)的返回值,而?map
?則將函數(shù)的返回值收集到一個新的數(shù)組中。
在內(nèi)部,這兩個函數(shù)可能會使用一個類似于下面的for
循環(huán)來遍歷數(shù)組:
for (let i = 0; i < array.length; i++) {callback(array[i], i, array); // callback 是 forEach 或 map 的參數(shù)函數(shù)
}
在?map
?的內(nèi)部實現(xiàn)中,還會有一個新的數(shù)組用于收集每次調(diào)用回調(diào)函數(shù)的結(jié)果。這個新的數(shù)組最后會被返回:
let newArray = [];
for (let i = 0; i < array.length; i++) {newArray.push(callback(array[i], i, array)); // callback 是 map 的參數(shù)函數(shù)
}
return newArray;
那么這個時候,有人可能會想,那我使用
forEach
的時候,加個return
不就得了,咱們先不說能不能實現(xiàn),就是真實現(xiàn)了,我覺得是沒什么實際意義的,盡管你可以在回調(diào)函數(shù)中添加返回語句,但這個返回值不會被?forEach
?方法捕獲或使用
那接下來咱們看看能不能實現(xiàn)吧
const array = [1, 2, 3]const result = array.forEach((element) => {return element * 2; // 這個返回值不會被 forEach 捕獲或使用});console.log(result); // 輸出: undefined
那么咱們使用map
呢
const array = [1, 2, 3]const result = array.map((element) => {return element * 2; // 這個返回值會被 map 捕獲或使用});console.log(result); // 輸出: [2, 4, 6]
到這里,我相信大家就能明白了
map和forEach會不會改變原數(shù)組
這需要看我們面對的數(shù)據(jù)類型,會分為基礎(chǔ)數(shù)據(jù)類型
和引用類型
基礎(chǔ)數(shù)據(jù)類型
forEach
const array = [1, 2, 3, 4];array.forEach(item => {item = item + 1})console.log(array); // [1,2,3,4]
map
const array = [1, 2, 3, 4];array.map(item => {item = item + 1})console.log(array); // [1,2,3,4]
我們發(fā)現(xiàn)是不會進行改變的
引用類型
const arr = [{name: 'shaka',age: 23}, {name: 'virgo',age: 18}]arr.forEach(item => {if (item.name === 'shaka') {item.age = 100}})console.log(arr); //[{name: 'shaka', age: 100}, {name: 'virgo', age: 18}]
map
就不再寫了,也是會改變的
所以重點來了,我們回到這個問題:問js的forEach和map的區(qū)別
,顯而易見一個會改變原數(shù)組,一個不會
這個答案毫無疑問是錯誤的
這里我們其實應(yīng)該思考的是,為什么基礎(chǔ)數(shù)據(jù)類型不會更改,引用類型會更改
這是因為在使用?forEach
?和?map
?方法時,對引用類型
元素的修改會直接反映在原始數(shù)組
中。這是因為引用類型的元素實際上存儲的是引用(內(nèi)存地址
),而非值本身
。因此,通過引用
可以訪問和修改原始數(shù)組
中的元素。
而number,string,Boolean,null,undefined
它們在棧內(nèi)存中直接存儲變量與值
我們再回頭看這個
為什么他這個修改了呢
因為使用的是
arr[index]
。相當于你平常的?數(shù)組名[第幾項] = 值
。這樣自然是可以修改的。
還有哪些區(qū)別呢
- foreach可以跳出循環(huán),
return
?語句可以當前回調(diào)函數(shù)中返回,而map不能,只能遍歷完整個數(shù)組。 - foreach不支持鏈式調(diào)用,而map支持鏈式調(diào)用,可以繼續(xù)對返回的新數(shù)組進行操作。
這里注意:forEach
?方法無法通過使用?break
?語句來中斷循環(huán)。?break
?語句用于中斷循環(huán)的功能只適用于?for
?循環(huán)或?while
?循環(huán)
這里給大家點例子吧,一下就能看懂了
// 使用 forEach 跳出當前循環(huán)const array1 = [1, 2, 3, 4, 5];let sum1 = 0;array1.forEach((element) => {if (element === 3) {return; // 使用 return 跳出循環(huán)}console.log(element); //1,2,4,5sum1 += element;});console.log(sum1); // 輸出: 12// 使用 map 無法中斷循環(huán)const array2 = [1, 2, 3, 4, 5];const newArray = array2.map((element) => {if (element === 3) {// 使用 return 語句無法中斷 map 循環(huán)return;}return element * 2;});console.log(newArray); // 輸出: [2, 4, undefined, 8, 10]// map 方法支持鏈式調(diào)用const array3 = [1, 2, 3, 4, 5];const doubledSum = array3.map((element) => element * 2).reduce((accumulator, currentValue) => accumulator + currentValue, 0);console.log(doubledSum); // 輸出: 30
const array = [1, 2, 3, 4, 5];let sum = 0;array.forEach((element) => {if (element === 3) {break; // 使用 break 無法中斷 forEach 循環(huán)}sum += element;});console.log(sum); // 此行代碼不會執(zhí)行,因為上面的代碼會拋出錯誤//for循環(huán)則可以const array = [1, 2, 3, 4, 5];let sum = 0;for (let i = 0; i < array.length; i++) {const element = array[i];if (element === 3) {break; // 使用 break 中斷 for 循環(huán)}sum += element;}console.log(sum); // 輸出: 3
作為數(shù)組
最常見的幾個api
之一,我覺得搞懂它是有必要的,當然,我這里說的其實是不全的,因為網(wǎng)上的文章較多,文檔也很詳細,這篇文章主要的目的是幫助一些小伙伴糾正一下~
最后,如有哪里不正確,請您指正~
致謝補充
這里是文章發(fā)出一段時間的致謝補充,很感謝評論區(qū)的一些建議和指正,主要是我在forEach
這里,說出了它可以跳出循環(huán)(本次循環(huán)),大家進行了指正
前端面試題庫 (面試必備)?? ? ? ? ? ?推薦:★★★★★
地址:前端面試題庫
【國慶頭像】- 國慶愛國 程序員頭像!總有一款適合你!