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