JavaScript數(shù)組高階函數(shù)之filter、map與reduce詳解
1. 函數(shù)式編程簡介
在JavaScript編程中,數(shù)組迭代是一項基礎(chǔ)而重要的任務(wù)。隨著函數(shù)式編程范式的普及,JavaScript提供了一系列強大的數(shù)組高階函數(shù),其中map、filter和reduce是最為核心和常用的三個方法。與傳統(tǒng)的命令式編程(如for循環(huán))相比,這些高階函數(shù)采用聲明式編程風(fēng)格,使代碼更加簡潔、可讀和易于維護。
函數(shù)式編程的核心思想是將函數(shù)作為第一公民,即函數(shù)可以像其他數(shù)據(jù)類型一樣被傳遞、賦值和返回。這種編程范式與面向?qū)ο缶幊绦纬甚r明對比,它更注重數(shù)據(jù)的轉(zhuǎn)換而非狀態(tài)的改變。在JavaScript中,數(shù)組高階函數(shù)正是這種思想的完美體現(xiàn)。
函數(shù)式編程是一種以函數(shù)為第一公民的編程范式,與命令式編程和面向?qū)ο缶幊绦纬蓪Ρ取T?JavaScript 中,數(shù)組的高階函數(shù) filter、map 和 reduce 是函數(shù)式編程的典型代表,它們可
以使代碼更加簡潔、易讀和可維護。
2. JavaScript數(shù)組迭代基礎(chǔ)
在深入探討高階函數(shù)之前,我們先簡要回顧JavaScript中數(shù)組迭代的基礎(chǔ)方法。
2.1 傳統(tǒng)迭代方法
for循環(huán)是最基礎(chǔ)的迭代方法,通過索引訪問數(shù)組的每個元素:
let array = [1, 2, 3, 4, 5];
for (let i = 0; i < array.length; i++) {
console.log(array[i]); // 輸出數(shù)組中的每個元素
}forEach方法是ES5引入的更簡潔的遍歷方式:
let array = [1, 2, 3, 4, 5];
array.forEach(function(item) {
console.log(item); // 輸出數(shù)組中的每個元素
});for...of循環(huán)是ES6引入的語法,直接迭代數(shù)組的元素:
let array = [1, 2, 3, 4, 5];
for (let item of array) {
console.log(item); // 輸出數(shù)組中的每個元素
}雖然這些方法都能實現(xiàn)數(shù)組迭代,但它們各有優(yōu)缺點。for循環(huán)靈活但代碼冗長;forEach簡潔但無法中斷遍歷;for...of語法簡潔但兼容性需要考慮。
2.2 高階函數(shù)的優(yōu)勢
與上述方法相比,map、filter和reduce等高階函數(shù)具有以下顯著優(yōu)勢:
聲明式編程:關(guān)注"做什么"而非"怎么做",代碼更易理解
不可變性:不會修改原數(shù)組,而是返回新數(shù)組,符合函數(shù)式編程原則
鏈?zhǔn)秸{(diào)用:可以輕松組合多個操作,形成清晰的數(shù)據(jù)處理管道
代碼復(fù)用:將通用邏輯抽象為函數(shù),提高代碼的可維護性
3. filter 函數(shù):數(shù)組過濾
基本概念
filter 函數(shù)用于創(chuàng)建一個新數(shù)組,包含通過指定函數(shù)測試的所有元素。它不會改變原始數(shù)組,而是返回一個新的過濾后的數(shù)組。
語法結(jié)構(gòu)
let newArray = arr.filter(function(currentValue[, index[, array]]) {
// 返回 true 保留元素,false 過濾元素
}[, thisArg])核心特性
過濾機制:根據(jù)回調(diào)函數(shù)返回的布爾值決定是否保留元素(
true保留,false過濾)應(yīng)用場景:從數(shù)組中篩選出滿足特定條件的元素
使用示例
const nums = [10, 20, 111, 222, 444, 40, 50]
let newNums = nums.filter(function(n) {
return n < 100
})
// 結(jié)果: [10, 20, 40, 50]箭頭函數(shù)簡化
let newNums = nums.filter(n => n < 100)
4. map 函數(shù):數(shù)組映射
基本概念
map 函數(shù)創(chuàng)建一個新數(shù)組,其結(jié)果是該數(shù)組中的每個元素都調(diào)用一個提供的函數(shù)后的返回值。它不會改變原數(shù)組,而是返回一個新數(shù)組。
語法結(jié)構(gòu)
let newArray = arr.map(function(currentValue[, index[, array]]) {
// 返回新元素值
}[, thisArg])核心特性
映射轉(zhuǎn)換:對數(shù)組中的每個元素應(yīng)用轉(zhuǎn)換函數(shù),生成新數(shù)組
應(yīng)用場景:將數(shù)組元素從一種形式轉(zhuǎn)換為另一種形式
使用示例
let new2Nums = newNums.map(function(n) {
return n * 2
})
// 結(jié)果: [20, 40, 80, 100]箭頭函數(shù)簡化
let new2Nums = newNums.map(n => n * 2)
5. reduce 函數(shù):數(shù)組匯總
基本概念
reduce 函數(shù)對數(shù)組中的每個元素執(zhí)行一個由您提供的 reducer 函數(shù),將其結(jié)果匯總為單個返回值。它是處理數(shù)組匯總操作的強大工具。
語法結(jié)構(gòu)
let result = arr.reduce(function(accumulator, currentValue[, index[, array]]) {
// 返回新的累加器值
}[, initialValue])核心特性
匯總聚合:將數(shù)組中的所有元素通過回調(diào)函數(shù)累加為一個最終值
參數(shù)說明:
accumulator:累加器,保存上一次回調(diào)的返回值currentValue:當(dāng)前正在處理的元素initialValue(可選):作為第一次調(diào)用回調(diào)函數(shù)的初始值
使用示例
let total = new2Nums.reduce(function(preValue, n) {
return preValue + n
}, 0)
// 結(jié)果: 240箭頭函數(shù)簡化
let total = new2Nums.reduce((pre, n) => pre + n, 0)
6. 鏈?zhǔn)秸{(diào)用:組合使用
這三個方法的真正威力在于可以將它們鏈?zhǔn)秸{(diào)用,創(chuàng)建出高效且表達性強的數(shù)據(jù)處理流程。
鏈?zhǔn)秸{(diào)用的開銷:每個方法都會生成新數(shù)組,處理大規(guī)模數(shù)據(jù)時可能影響性能。此時可考慮使用 for循環(huán)合并操作。
完整示例
// 分開調(diào)用
let total = nums.filter(n => n < 100)
.map(n => n * 2)
.reduce((pre, n) => pre + n, 0)
// 單行簡潔寫法
let total = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n)復(fù)雜數(shù)據(jù)處理示例
// 處理對象數(shù)組的復(fù)雜案例
let users = [
{ name: 'Alice', age: 22 },
{ name: 'Bob', age: 17 },
{ name: 'Charlie', age: 30 }
]
let totalAge = users.filter(user => user.age > 18)
.map(user => user.age)
.reduce((sum, age) => sum + age, 0)
// 結(jié)果: 527. 三種方法對比總結(jié)
方法 | 返回類型 | 是否修改原數(shù)組 | 主要用途 |
|---|---|---|---|
filter | 新數(shù)組 | 否 | 過濾數(shù)組中符合條件的元素 |
map | 新數(shù)組 | 否 | 轉(zhuǎn)換數(shù)組中的每個元素 |
reduce | 任意類型(單個值) | 否 | 將數(shù)組聚合為一個值 |
8. 性能考慮與優(yōu)化建議
雖然這些高階函數(shù)提供了聲明式和簡潔的數(shù)組處理方式,但在處理大型數(shù)據(jù)集時,它們的性能可能不如傳統(tǒng)的 for 循環(huán)。這是因為高階函數(shù)在內(nèi)部會進行循環(huán)迭代,但額外的函數(shù)調(diào)用和上下文切換可能會引入額外開銷。
優(yōu)化建議:
避免不必要的鏈?zhǔn)秸{(diào)用,盡量在一個迭代中完成多個操作
處理大型數(shù)據(jù)集時,考慮使用傳統(tǒng)的 for 循環(huán)
鏈?zhǔn)秸{(diào)用時,先使用 filter 方法減少數(shù)據(jù)集,再進行 map 和 reduce 操作
9. 實際應(yīng)用場景
數(shù)據(jù)處理管道
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let result = data.filter(num => num % 2 === 0) // 篩選偶數(shù)
.map(num => num * 2) // 乘以2
.filter(num => num > 5) // 篩選大于5的數(shù)
.reduce((sum, num) => sum + num, 0) // 求和
// 結(jié)果: 24數(shù)組去重
let arr = [1, 2, 2, 3, 4, 4, 5]
let uniqueArr = arr.filter((value, index, self) => {
return self.indexOf(value) === index
})
// 結(jié)果: [1, 2, 3, 4, 5]這些數(shù)組高階函數(shù)是現(xiàn)代 JavaScript 開發(fā)中的重要工具,掌握它們能夠幫助你寫出更簡潔、優(yōu)雅和可維護的代碼。
到此這篇關(guān)于JavaScript數(shù)組高階函數(shù)之filter、map與reduce詳解的文章就介紹到這了,更多相關(guān)JS數(shù)組高階函數(shù)filter、map與reduce內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
uniapp插件uview下表單無法動態(tài)校驗的問題解決
最近項目中用到了uview?在做表單時用到了校驗,發(fā)現(xiàn)校驗不友好的結(jié)果,下面這篇文章主要給大家介紹了關(guān)于uniapp插件uview下表單無法動態(tài)校驗的問題解決,需要的朋友可以參考下2022-12-12
JavaScript中不冒泡的DOM事件的使用小結(jié)
本文主要介紹了JavaScript中不冒泡的DOM事件的使用小結(jié),包括常見的focus、blur、load、unload等事件,并提供了解決方案,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2026-03-03
學(xué)習(xí)JavaScript設(shè)計模式之狀態(tài)模式
這篇文章主要為大家介紹了JavaScript設(shè)計模式中的狀態(tài)模式,對JavaScript設(shè)計模式感興趣的小伙伴們可以參考一下2016-01-01
小議Function.apply() 之一------(函數(shù)的劫持與對象的復(fù)制)
小議Function.apply() 之一------(函數(shù)的劫持與對象的復(fù)制)...2006-11-11
Javscript刪除數(shù)組中指定元素并返回新數(shù)組
把數(shù)組中某個值刪除,并返回新數(shù)組,需要遍歷舊數(shù)組找到要刪除的元素,下面有個不錯的示例,大家可以參考下2014-03-03

