JavaScript數(shù)組方法reduce使用詳解
一,前言
Reduce 是一種在函數(shù)式編程中常見的操作,它可以將一個(gè)序列(比如列表,數(shù)組)的所有元素通過某種規(guī)約邏輯合并成一個(gè)單一的數(shù)值。Reduce 的概念最早起源于函數(shù)式編程語言 Lisp,后來被廣泛應(yīng)用于其他語言中,如 Python ,javaScript。本文會用最易懂的方式幫你徹底掌握J(rèn)avaScript數(shù)組reduce()方法。我們先從基礎(chǔ)開始,逐步深入,最后通過實(shí)際案例鞏固知識,最重要的是希望能夠帶給你一些思考。
二,核心語法
arr.reduce(callback(accumulator, currentValue, index, array), initialValue)
Accumulator(累計(jì)值)
CurrentValue(當(dāng)前元素)
Index(當(dāng)前索引)
Array(原數(shù)組)
initialValue(Accumulator的初始值)
三,案例
1.求和
const nums = [1, 2, 3]; const sum = nums.reduce((acc, num) => acc + num, 0);
代碼分析:
此求和案例分別用了參數(shù)acc和num代表Accumulator和CurrentValue,并且將Accumulator的初始值賦為0。
運(yùn)算步驟:
1,初始值為0,acc為0加第一次的當(dāng)前值1 返回1
2,acc為1加第二次循環(huán)的當(dāng)前值2,返回3
3,acc為3加第三次循環(huán)的當(dāng)前值3,返回6
2.找最大值
const max = [4, 2, 7, 5].reduce((a, b) => Math.max(a, b), -Infinity);
代碼分析:
此求最大值案例分別用了參數(shù)a和b代表Accumulator和CurrentValue,并且將Accumulator的初始值賦為-Infinity(負(fù)無窮大)。
運(yùn)算步驟:
1,首先是負(fù)無窮和第一次的當(dāng)前值4比較,返回4
2,a為4,和第二次的當(dāng)前值2比較,返回4
3,a為4,和第三次當(dāng)前值7比較,返回7
4,a為7,和第四次當(dāng)前值5比較,返回7
說明:
-Infinity 是 JavaScript 中的一個(gè)特殊值,表示負(fù)無窮大。它不是變量,而是一個(gè)全局屬性,屬于 JavaScript 的 基本數(shù)據(jù)類型 之一。
這里也可以更換 -Infinity為100,那么max的返回值就是100。
3.數(shù)組轉(zhuǎn)對象
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
const userMap = users.reduce((obj, user) => {
obj[user.id] = user;
return obj;
}, {});
返回結(jié)果:
{
"1": {
"id": 1,
"name": "Alice"
},
"2": {
"id": 2,
"name": "Bob"
}
}
說明:
數(shù)組轉(zhuǎn)對象案例這里主要是想體現(xiàn)一下設(shè)置初始值的重要性
這里如果不設(shè)置其默認(rèn)初始值可以先看一下返回結(jié)果的區(qū)別
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
const userMap = users.reduce((obj, user) => {
obj[user.id] = user;
return obj;
});
返回值:
{
"2": {
"id": 2,
"name": "Bob"
},
"id": 1,
"name": "Alice"
}
代碼分析:
要想弄明白為什么沒有設(shè)置空的初始值顯示結(jié)果是這樣,我們首先回到案例1求和的代碼,之前我們分析結(jié)論是基于有返回值的情況下得出的
1,初始值為0,acc為0加第一次的當(dāng)前值1 返回1
2,acc為1加第二次循環(huán)的當(dāng)前值2,返回3
3,acc為3加第三次循環(huán)的當(dāng)前值3,返回6
那么如果對于求和案例不設(shè)置初始值又該如何分析呢?
對于沒有設(shè)置初始值的reduce分析:第一次迭代時(shí),acc 是數(shù)組的第一個(gè)元素,num 是數(shù)組的第二個(gè)元素。得到這個(gè)結(jié)論我們返回來分析代碼:
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
const userMap = users.reduce((obj, user) => {
obj[user.id] = user;
return obj;
});
因?yàn)闆]有返回值,第一次obj是 { id: 1, name: ‘Alice’ },user是 { id: 2, name: ‘Bob’ }
執(zhí)行 obj[user.id] = user 后,obj 變?yōu)?{ id: 1, name: ‘Alice’, 2: { id: 2, name: ‘Bob’ } }。
注意:
JavaScript的reduce函數(shù)有沒有設(shè)置初始值,直接影響第一次執(zhí)行的Accumulator和CurrentValue
4.復(fù)合操作(同時(shí)實(shí)現(xiàn) map + filter)
const numbers = [1, 2, 3, 4];
const doubledEvens = numbers.reduce((arr, num) => {
if (num % 2 === 0) {
arr.push(num * 2);
}
return arr;
}, []);
// 結(jié)果:[4, 8](先過濾偶數(shù),再翻倍)
代碼分析:
此求和案例分別用了參數(shù)arr和num代表Accumulator和CurrentValue,并且將Accumulator的初始值賦為[]。此例子中必須要設(shè)置Accumulator的初始值為[ ],否則,Accumulator的初始值是1,不是數(shù)組沒有push方法就會報(bào)錯。
四,常見錯誤
1.空數(shù)組沒有初始值
[].reduce((a, b) => a + b); // 報(bào)錯!
2.沒有返回累加值
// 錯誤示例
[1,2,3].reduce((acc, num) => {
acc + num; // 沒有 return!
});
// 正確:必須顯式返回 acc
reduce 方法在遍歷數(shù)組時(shí),依賴于數(shù)組的長度和內(nèi)容,如果在遍歷過程中修改了數(shù)組(例如刪除元素),會導(dǎo)致遍歷邏輯混亂,結(jié)果不可預(yù)測。
五,reduce 的 polyfill
Polyfill 是指在不支持某個(gè)新特性的舊瀏覽器中,用 JavaScript 實(shí)現(xiàn)該特性的代碼。換句話說,它是一個(gè)“補(bǔ)丁”,用來填補(bǔ)瀏覽器原生功能的缺失。
用白話說就是自己實(shí)現(xiàn)reduce,通過自己實(shí)現(xiàn) reduce,可以更深入地理解它的工作原理。
Array.prototype.myReduce = function (callback, initialValue) {
// 1. 檢查 this 是否為 null 或 undefined
if (this == null) {
throw new TypeError('Array.prototype.myReduce called on null or undefined');
}
// 2. 檢查 callback 是否是函數(shù)
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
const array = Object(this); // 將 this 轉(zhuǎn)換為對象
const length = array.length >>> 0; // 確保 length 是正整數(shù)
let accumulator;
let startIndex = 0;
// 3. 處理初始值
if (arguments.length >= 2) {
accumulator = initialValue; // 如果有初始值,直接使用
} else {
// 如果沒有初始值,取數(shù)組的第一個(gè)元素作為初始值
if (length === 0) {
throw new TypeError('Reduce of empty array with no initial value');
}
accumulator = array[0];
startIndex = 1; // 從第二個(gè)元素開始遍歷
}
// 4. 遍歷數(shù)組
for (let i = startIndex; i < length; i++) {
if (i in array) {
// 調(diào)用回調(diào)函數(shù),更新 accumulator
accumulator = callback(accumulator, array[i], i, array);
}
}
// 5. 返回最終結(jié)果
return accumulator;
};
使用示例:
const nums = [1, 2, 3, 4]; // 求和 const sum = nums.myReduce((acc, num) => acc + num, 0); console.log(sum); // 10 // 找最大值 const max = nums.myReduce((acc, num) => Math.max(acc, num), -Infinity); console.log(max); // 4 // 數(shù)組轉(zhuǎn)字符串 const str = nums.myReduce((acc, num) => acc + num.toString(), ''); console.log(str); // '1234'
六,總結(jié)
reduce的參數(shù)看起來多,但是認(rèn)真體會上面的案例不難理解,難點(diǎn)是如何記住
Accumulator(累計(jì)值)
CurrentValue(當(dāng)前元素)
Index(當(dāng)前索引)
Array(原數(shù)組)
參數(shù)順序口訣:“All Cows In Australia”(ACIA)
以上就是JavaScript數(shù)組方法reduce詳解的詳細(xì)內(nèi)容,更多關(guān)于JavaScript方法reduce的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js實(shí)現(xiàn)1,2,3,5數(shù)字按照概率生成
這篇文章主要介紹了js實(shí)現(xiàn)1,2,3,5數(shù)字按照概率生成,需要的朋友可以參考下2017-09-09
JS實(shí)現(xiàn)狀態(tài)欄跑馬燈文字效果代碼
這篇文章主要介紹了JS實(shí)現(xiàn)狀態(tài)欄跑馬燈文字效果代碼,涉及JavaScript定時(shí)函數(shù)及流程控制的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10
JS實(shí)現(xiàn)隨機(jī)生成驗(yàn)證碼
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)隨機(jī)生成驗(yàn)證碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
JavaScript是否可實(shí)現(xiàn)多線程 深入理解JavaScript定時(shí)機(jī)制
JavaScript的setTimeout與setInterval是兩個(gè)很容易欺騙別人感情的方法,因?yàn)槲覀冮_始常常以為調(diào)用了就會按既定的方式執(zhí)行, 我想不少人都深有同感,2009-12-12

