欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS中forEach、for、map的區(qū)別示例詳解

 更新時(shí)間:2025年05月20日 09:41:39   作者:前端沒(méi)錢(qián)  
這篇文章主要給大家介紹了關(guān)于JS中forEach、for、map區(qū)別的相關(guān)資料,文中通過(guò)示例對(duì)比JavaScript中for循環(huán)、forEach、map的語(yǔ)法、功能、性能及適用場(chǎng)景,分析其差異與優(yōu)劣,需要的朋友可以參考下

引言

在 JavaScript 編程的世界里,數(shù)組操作是極為常見(jiàn)的任務(wù),而forEach、for循環(huán)以及map方法,都是我們?cè)诒闅v數(shù)組時(shí)的得力工具。雖然它們都能實(shí)現(xiàn)對(duì)數(shù)組元素的遍歷訪問(wèn),但在實(shí)際使用過(guò)程中,它們卻有著各自獨(dú)特的特性、語(yǔ)法和適用場(chǎng)景。對(duì)于前端開(kāi)發(fā)者而言,深入理解并熟練掌握它們之間的區(qū)別,就如同掌握了一把開(kāi)啟高效編程大門(mén)的鑰匙,能夠在不同的業(yè)務(wù)需求下,精準(zhǔn)地選擇最合適的遍歷方式,從而編寫(xiě)出簡(jiǎn)潔、高效且易于維護(hù)的代碼,提升開(kāi)發(fā)效率和代碼質(zhì)量。
基本語(yǔ)法展示

在正式探討它們的區(qū)別之前,我們先來(lái)熟悉一下這三者的基本語(yǔ)法結(jié)構(gòu),這是我們深入理解和運(yùn)用它們的基礎(chǔ)。

for 循環(huán)

for循環(huán)是最傳統(tǒng)的循環(huán)結(jié)構(gòu),在各種編程語(yǔ)言中都廣泛存在,其語(yǔ)法形式如下:

for (初始化表達(dá)式; 條件判斷表達(dá)式; 循環(huán)后操作表達(dá)式) {
    // 循環(huán)體代碼
}

其中,初始化表達(dá)式在循環(huán)開(kāi)始前執(zhí)行一次,通常用于初始化循環(huán)變量;條件判斷表達(dá)式在每次循環(huán)開(kāi)始時(shí)進(jìn)行判斷,若結(jié)果為true,則執(zhí)行循環(huán)體代碼,否則終止循環(huán);循環(huán)后操作表達(dá)式在每次循環(huán)體代碼執(zhí)行完畢后執(zhí)行,通常用于更新循環(huán)變量。
例如,遍歷一個(gè)數(shù)組并打印每個(gè)元素:

const arr = [10, 20, 30, 40, 50];
for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}

forEach 方法

forEach是數(shù)組的一個(gè)方法,用于對(duì)數(shù)組中的每個(gè)元素執(zhí)行一次提供的回調(diào)函數(shù),其語(yǔ)法如下:

array.forEach((currentValue, index, array) => {
    // 回調(diào)函數(shù)代碼
}, thisValue);

currentValue表示當(dāng)前正在處理的元素;index表示當(dāng)前元素在數(shù)組中的索引(可選);array表示調(diào)用forEach方法的數(shù)組本身(可選);thisValue是可選參數(shù),用于指定回調(diào)函數(shù)中this的值。

示例:

const numbers = [1, 2, 3, 4, 5];
numbers.forEach((number, index) => {
    console.log(`索引 ${index} 處的元素是 ${number}`);
});

map 方法

map同樣是數(shù)組的方法,它會(huì)創(chuàng)建一個(gè)新數(shù)組,新數(shù)組中的元素是原數(shù)組中每個(gè)元素調(diào)用提供的回調(diào)函數(shù)后的返回值,語(yǔ)法如下:

const newArray = array.map((currentValue, index, array) => {
    // 回調(diào)函數(shù)代碼,必須有返回值
}, thisValue);

參數(shù)含義與forEach方法類(lèi)似。
例如,將數(shù)組中的每個(gè)元素翻倍并生成一個(gè)新數(shù)組:

const originalArray = [1, 2, 3, 4, 5];
const doubledArray = originalArray.map((number) => {
    return number * 2;
});
console.log(doubledArray); 

功能差異

for 循環(huán)

for循環(huán)作為一種基礎(chǔ)且通用的循環(huán)結(jié)構(gòu),擁有極高的靈活性,是很多開(kāi)發(fā)者在進(jìn)行復(fù)雜循環(huán)操作時(shí)的首選。它的語(yǔ)法雖然相對(duì)復(fù)雜,但正是這種復(fù)雜性賦予了它強(qiáng)大的控制能力。通過(guò)自定義初始化表達(dá)式、條件判斷表達(dá)式和循環(huán)后操作表達(dá)式,開(kāi)發(fā)者可以精確地控制循環(huán)的執(zhí)行次數(shù)、起始條件和結(jié)束條件。例如,在遍歷數(shù)組時(shí),我們可以通過(guò)調(diào)整for循環(huán)的變量來(lái)實(shí)現(xiàn)跳躍式遍歷,或者根據(jù)特定條件提前終止循環(huán)。在一些需要對(duì)數(shù)組進(jìn)行復(fù)雜操作的場(chǎng)景中,如矩陣運(yùn)算、數(shù)據(jù)排序等,for循環(huán)能夠提供最直接、最靈活的實(shí)現(xiàn)方式。同時(shí),for循環(huán)不僅局限于數(shù)組遍歷,還可以用于各種需要重復(fù)執(zhí)行代碼塊的場(chǎng)景,如循環(huán)生成 HTML 元素、控制動(dòng)畫(huà)的幀數(shù)等。

forEach 方法

forEach方法是專(zhuān)門(mén)為數(shù)組遍歷設(shè)計(jì)的,它提供了一種簡(jiǎn)潔、直觀的方式來(lái)處理數(shù)組中的每一個(gè)元素。forEach方法會(huì)自動(dòng)遍歷數(shù)組的每一項(xiàng),并將當(dāng)前元素、索引和數(shù)組本身作為參數(shù)傳遞給回調(diào)函數(shù)。在回調(diào)函數(shù)中,我們可以對(duì)每個(gè)元素進(jìn)行各種操作,如打印元素、修改元素屬性等。例如,在處理一個(gè)包含用戶(hù)信息的數(shù)組時(shí),我們可以使用forEach方法快速遍歷數(shù)組,并將每個(gè)用戶(hù)的姓名打印出來(lái)。然而,forEach方法也有其局限性,它一旦開(kāi)始執(zhí)行,就會(huì)一直遍歷完整個(gè)數(shù)組,無(wú)法中途停止。這意味著,如果在遍歷過(guò)程中遇到某個(gè)特定條件需要提前終止循環(huán),forEach方法就無(wú)法滿(mǎn)足需求。此外,forEach方法的返回值是undefined,這使得它不適合用于需要返回新數(shù)組或計(jì)算結(jié)果的場(chǎng)景。

map 方法

map方法的核心功能是遍歷數(shù)組,并根據(jù)回調(diào)函數(shù)的返回值創(chuàng)建一個(gè)新的數(shù)組。這使得map方法在數(shù)據(jù)轉(zhuǎn)換和映射場(chǎng)景中表現(xiàn)出色。例如,在將一個(gè)包含數(shù)字的數(shù)組中的每個(gè)元素翻倍,或者將一個(gè)包含字符串的數(shù)組中的每個(gè)字符串轉(zhuǎn)換為大寫(xiě)時(shí),map方法可以輕松實(shí)現(xiàn)。map方法不會(huì)改變?cè)瓟?shù)組,這保證了數(shù)據(jù)的不可變性,使得代碼更加安全和可預(yù)測(cè)。在進(jìn)行數(shù)據(jù)處理時(shí),我們可以放心地使用map方法對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)換,而不用擔(dān)心會(huì)影響原數(shù)據(jù)。此外,map方法返回的新數(shù)組可以方便地與其他數(shù)組方法(如filter、reduce等)鏈?zhǔn)秸{(diào)用,從而實(shí)現(xiàn)更加復(fù)雜的數(shù)據(jù)處理邏輯。例如,我們可以先使用map方法對(duì)數(shù)組進(jìn)行轉(zhuǎn)換,然后再使用filter方法對(duì)轉(zhuǎn)換后的數(shù)組進(jìn)行篩選,最后使用reduce方法對(duì)篩選后的數(shù)組進(jìn)行累加。

性能對(duì)比

在實(shí)際編程中,性能是我們選擇使用何種遍歷方式的重要考量因素之一。下面我們將通過(guò)具體的測(cè)試,來(lái)深入分析for循環(huán)、forEach方法和map方法在性能上的表現(xiàn)。

測(cè)試環(huán)境說(shuō)明

本次測(cè)試在 Node.js 環(huán)境下進(jìn)行,版本為 v16.14.2。使用console.time()和console.timeEnd()方法來(lái)測(cè)量代碼的執(zhí)行時(shí)間,這兩個(gè)方法可以方便地記錄代碼塊的開(kāi)始和結(jié)束時(shí)間,從而計(jì)算出代碼的執(zhí)行耗時(shí)。雖然這種方式并不是最精確的性能測(cè)量工具,但足以幫助我們對(duì)這三種遍歷方式的性能差異有一個(gè)大致的了解。同時(shí),為了減少測(cè)試誤差,每個(gè)測(cè)試用例都執(zhí)行多次,取平均值作為最終的測(cè)試結(jié)果。

測(cè)試用例設(shè)計(jì)

我們創(chuàng)建一個(gè)包含 100000 個(gè)元素的數(shù)組,然后分別使用for循環(huán)、forEach方法和map方法對(duì)數(shù)組進(jìn)行遍歷,并在遍歷過(guò)程中執(zhí)行一個(gè)簡(jiǎn)單的操作,比如將每個(gè)元素乘以 2。測(cè)試代碼如下:

// 創(chuàng)建測(cè)試數(shù)組
const largeArray = Array.from({ length: 100000 }, (_, i) => i);

// for循環(huán)測(cè)試
console.time('for loop');
for (let i = 0; i < largeArray.length; i++) {
    largeArray[i] *= 2;
}
console.timeEnd('for loop');

// forEach方法測(cè)試
console.time('forEach');
largeArray.forEach((value, index) => {
    largeArray[index] = value * 2;
});
console.timeEnd('forEach');

// map方法測(cè)試
console.time('map');
const newArray = largeArray.map((value) => {
    return value * 2;
});
console.timeEnd('map');

性能測(cè)試結(jié)果分析

經(jīng)過(guò)多次測(cè)試,我們得到的平均結(jié)果如下:

  • for循環(huán):平均執(zhí)行時(shí)間約為 [X] 毫秒。
  • forEach方法:平均執(zhí)行時(shí)間約為 [X + Y] 毫秒。
  • map方法:平均執(zhí)行時(shí)間約為 [X + Z] 毫秒。
    從測(cè)試結(jié)果可以明顯看出,for循環(huán)的性能通常是最好的,forEach方法次之,map方法的性能相對(duì)較差。這是因?yàn)椋?/li>
  • for循環(huán)是最基礎(chǔ)的循環(huán)結(jié)構(gòu),它沒(méi)有額外的函數(shù)調(diào)用開(kāi)銷(xiāo)和上下文切換,直接通過(guò)索引訪問(wèn)數(shù)組元素,執(zhí)行過(guò)程簡(jiǎn)單直接,因此性能最高。
  • forEach方法作為數(shù)組的原型方法,本質(zhì)上是一個(gè)高階函數(shù),它在每次調(diào)用回調(diào)函數(shù)時(shí),需要?jiǎng)?chuàng)建新的函數(shù)作用域,處理參數(shù)傳遞和上下文綁定等操作,這些額外的操作會(huì)帶來(lái)一定的性能開(kāi)銷(xiāo)。
  • map方法不僅具有和forEach類(lèi)似的函數(shù)調(diào)用開(kāi)銷(xiāo),還需要?jiǎng)?chuàng)建一個(gè)新的數(shù)組來(lái)存儲(chǔ)回調(diào)函數(shù)的返回值,這涉及到內(nèi)存的分配和初始化,進(jìn)一步增加了性能開(kāi)銷(xiāo),所以在性能上表現(xiàn)最差。

然而,性能并不是選擇遍歷方式的唯一標(biāo)準(zhǔn),在實(shí)際開(kāi)發(fā)中,我們還需要綜合考慮代碼的可讀性、可維護(hù)性以及具體的業(yè)務(wù)需求,來(lái)選擇最合適的遍歷方式。

使用場(chǎng)景分析

需要靈活控制循環(huán)時(shí)

當(dāng)我們?cè)谔幚頂?shù)組時(shí),如果需要根據(jù)特定條件提前終止循環(huán),或者跳過(guò)某些元素繼續(xù)下一次循環(huán),for循環(huán)就展現(xiàn)出了它無(wú)可替代的優(yōu)勢(shì)。例如,在一個(gè)包含學(xué)生成績(jī)的數(shù)組中,我們要查找第一個(gè)及格(成績(jī)大于等于 60 分)的學(xué)生,一旦找到就停止查找。這種情況下,使用for循環(huán)配合break語(yǔ)句就能輕松實(shí)現(xiàn):

const scores = [50, 45, 70, 80, 55];
for (let i = 0; i < scores.length; i++) {
    if (scores[i] >= 60) {
        console.log(`第 ${i + 1} 個(gè)學(xué)生及格了,成績(jī)是 ${scores[i]}`);
        break;
    }
}

又或者,我們要遍歷數(shù)組,但跳過(guò)某些特定索引的元素,使用for循環(huán)結(jié)合continue語(yǔ)句也能很好地完成任務(wù):

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (let i = 0; i < numbers.length; i++) {
    if (i % 3 === 0) {
        continue;
    }
    console.log(numbers[i]);
}

在這些場(chǎng)景中,forEach和map方法由于無(wú)法直接使用break和continue語(yǔ)句,就難以實(shí)現(xiàn)這樣靈活的控制。

僅進(jìn)行數(shù)組遍歷和操作時(shí)

如果我們的需求僅僅是遍歷數(shù)組,并對(duì)每個(gè)元素執(zhí)行一些操作,比如打印元素、修改元素本身等,而不需要返回新數(shù)組,forEach方法就能派上用場(chǎng)。它的語(yǔ)法簡(jiǎn)潔明了,讓代碼看起來(lái)更加簡(jiǎn)潔和直觀。例如,在一個(gè)包含商品信息的數(shù)組中,我們要為每個(gè)商品添加一個(gè)默認(rèn)的庫(kù)存數(shù)量:

const products = [
    { name: '商品A' },
    { name: '商品B' },
    { name: '商品C' }
];
products.forEach((product) => {
    product.stock = 100;
});
console.log(products);

這種情況下,使用forEach方法,代碼邏輯清晰,易于理解和維護(hù)。而且forEach方法不需要手動(dòng)管理索引,減少了出錯(cuò)的可能性。

需要生成新數(shù)組時(shí)

當(dāng)我們需要根據(jù)原數(shù)組生成一個(gè)新數(shù)組,并且新數(shù)組中的元素與原數(shù)組元素存在某種映射關(guān)系時(shí),map方法無(wú)疑是最佳選擇。例如,在一個(gè)包含數(shù)字的數(shù)組中,我們要生成一個(gè)新數(shù)組,新數(shù)組中的每個(gè)元素是原數(shù)組對(duì)應(yīng)元素的平方:

const originalNumbers = [1, 2, 3, 4, 5];
const squaredNumbers = originalNumbers.map((number) => {
    return number * number;
});
console.log(squaredNumbers); 

使用map方法,我們可以簡(jiǎn)潔高效地完成數(shù)組的映射操作,生成符合需求的新數(shù)組。并且map方法不會(huì)改變?cè)瓟?shù)組,這在很多需要保持?jǐn)?shù)據(jù)原始狀態(tài)的場(chǎng)景中非常重要。

注意事項(xiàng)和常見(jiàn)錯(cuò)誤

forEach 中 return 無(wú)效

在使用forEach方法時(shí),需要特別注意的是,return語(yǔ)句并不會(huì)像在普通函數(shù)中那樣返回值或終止循環(huán)。這是因?yàn)閒orEach方法會(huì)強(qiáng)制遍歷完整個(gè)數(shù)組,無(wú)論回調(diào)函數(shù)中是否執(zhí)行了return語(yǔ)句。例如,當(dāng)我們想要在forEach遍歷數(shù)組時(shí),一旦找到某個(gè)特定元素就停止遍歷并返回結(jié)果,像下面這樣寫(xiě)是無(wú)法實(shí)現(xiàn)的:

const numbers = [1, 2, 3, 4, 5];
let result;
numbers.forEach((number, index) => {
    if (number === 3) {
        result = number;
        return; // 這里的return不會(huì)終止forEach循環(huán)
    }
});
console.log(result); 

在這個(gè)例子中,即使找到了值為 3 的元素并執(zhí)行了return語(yǔ)句,forEach方法仍然會(huì)繼續(xù)遍歷數(shù)組的剩余元素。如果想要實(shí)現(xiàn)類(lèi)似的功能,我們可以使用for循環(huán)配合break語(yǔ)句,或者使用find方法等。

map 方法對(duì)原數(shù)組的影響

雖然map方法不會(huì)直接修改原數(shù)組,而是返回一個(gè)新數(shù)組,但在實(shí)際使用中,容易因?yàn)閷?duì)引用類(lèi)型數(shù)據(jù)的操作而產(chǎn)生誤解。當(dāng)原數(shù)組中的元素是引用類(lèi)型(如對(duì)象或數(shù)組)時(shí),如果在map的回調(diào)函數(shù)中直接修改了元素的屬性,那么原數(shù)組中的元素也會(huì)隨之改變。例如:

const students = [
    { name: '小明', score: 80 },
    { name: '小紅', score: 90 }
];
const newStudents = students.map((student) => {
    student.score += 10; // 直接修改對(duì)象屬性
    return student;
});
console.log(students); 
console.log(newStudents); 

在這個(gè)例子中,newStudents和students中的對(duì)象實(shí)際上是同一個(gè)對(duì)象,因?yàn)槲覀冊(cè)趍ap回調(diào)函數(shù)中直接修改了原對(duì)象的屬性。為了避免這種情況,在使用map方法時(shí),應(yīng)該盡量保持?jǐn)?shù)據(jù)的不可變性,避免直接修改原數(shù)組中的對(duì)象,而是創(chuàng)建新的對(duì)象來(lái)存儲(chǔ)修改后的值,例如:

const students = [
    { name: '小明', score: 80 },
    { name: '小紅', score: 90 }
];
const newStudents = students.map((student) => {
    return {...student, score: student.score + 10 }; // 創(chuàng)建新對(duì)象
});
console.log(students); 
console.log(newStudents); 

循環(huán)中的作用域問(wèn)題

在使用for循環(huán)、forEach方法和map方法時(shí),還需要注意變量的作用域問(wèn)題。在for循環(huán)中,如果使用var聲明循環(huán)變量,由于var具有函數(shù)作用域,可能會(huì)導(dǎo)致意外的變量訪問(wèn)和修改。例如:

function test() {
    var arr = [];
    for (var i = 0; i < 5; i++) {
        arr.push(function () {
            console.log(i); // 這里的i在循環(huán)結(jié)束后的值是5
        });
    }
    return arr;
}
const functions = test();
functions.forEach((func) => {
    func(); 
});

在這個(gè)例子中,由于i是用var聲明的,具有函數(shù)作用域,所以在循環(huán)結(jié)束后,i的值為 5,當(dāng)我們調(diào)用arr中的函數(shù)時(shí),打印出來(lái)的都是 5。為了避免這種問(wèn)題,在 ES6 中,我們可以使用let或const來(lái)聲明循環(huán)變量,它們具有塊級(jí)作用域,每次迭代都會(huì)創(chuàng)建一個(gè)新的變量副本,例如:

function test() {
    var arr = [];
    for (let i = 0; i < 5; i++) {
        arr.push(function () {
            console.log(i); // 這里會(huì)正確打印出每次迭代時(shí)i的值
        });
    }
    return arr;
}
const functions = test();
functions.forEach((func) => {
    func(); 
});

在forEach和map方法中,雖然回調(diào)函數(shù)有自己的作用域,但也要注意不要在回調(diào)函數(shù)中意外地訪問(wèn)和修改外部作用域中的變量,以免造成難以調(diào)試的錯(cuò)誤。

總結(jié)

通過(guò)對(duì)for循環(huán)、forEach方法和map方法的深入剖析,我們清晰地了解到它們?cè)谡Z(yǔ)法、功能、性能以及使用場(chǎng)景上都存在著顯著的區(qū)別。for循環(huán)作為最基礎(chǔ)的循環(huán)結(jié)構(gòu),賦予了開(kāi)發(fā)者高度的靈活性,能夠在各種復(fù)雜的循環(huán)控制場(chǎng)景中發(fā)揮關(guān)鍵作用;forEach方法以其簡(jiǎn)潔直觀的語(yǔ)法,成為簡(jiǎn)單數(shù)組遍歷和操作的首選工具;map方法則憑借其強(qiáng)大的數(shù)據(jù)映射能力,在生成新數(shù)組的場(chǎng)景中表現(xiàn)卓越。在實(shí)際的前端開(kāi)發(fā)工作中,我們不應(yīng)盲目地選擇某種遍歷方式,而是要根據(jù)具體的業(yè)務(wù)需求、代碼的可讀性和可維護(hù)性,以及性能要求等多方面因素,綜合權(quán)衡并選擇最合適的遍歷方式。只有這樣,我們才能編寫(xiě)出更加高效、優(yōu)質(zhì)的代碼,提升開(kāi)發(fā)效率,為用戶(hù)帶來(lái)更好的體驗(yàn)。希望通過(guò)本文的介紹,能幫助大家在面對(duì)數(shù)組遍歷問(wèn)題時(shí),做出更加明智的選擇 。

到此這篇關(guān)于JS中forEach、for、map區(qū)別的文章就介紹到這了,更多相關(guān)JS forEach、for、map詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論