翻譯: 劉小夕javascript
原文連接:css-tricks.com/understandi…css
更多文章可戳: github.com/YvetteLau/B…html
有一些小夥伴,對JavaScript的 reduce
方法還不夠理解,咱們來看下面兩段代碼:java
const nums = [1, 2, 3];
let value = 0;
for (let i = 0; i < nums.length; i++) {
value += nums[i];
}
複製代碼
const nums = [1, 2, 3];
const value = nums.reduce((ac, next) => ac + next, 0);
複製代碼
這兩段代碼在功能上是等價的,都是數組中全部數字的總和,可是它們之間有一些理念差別。讓咱們先研究一下 reducer
,由於它們功能強大,並且在編程中很重要。有成百上千篇關於 reducer
的文章,最後我會連接我喜歡的文章。git
reducer
是什麼要理解 reducer
的第一點也是最重要的一點是它永遠返回一個值,這個值能夠是數字、字符串、數組或對象,但它始終只能是一個。reducer
對於不少場景都很適用,可是它們對於將一種邏輯應用到一組值中並最終獲得一個單一結果的狀況特別適用。github
另外須要說明:reducer
本質上不會改變你的初始值;相反,它們會返回一些其餘的東西。shell
讓咱們回顧一下第一個例子,這樣你就能夠看到這裏發生了什麼,一塊兒看一下下面的gif:編程
觀看gif也許對咱們全部幫助,不過仍是要回歸代碼:數組
const nums = [1, 2, 3];
let value = 0;
for (let i = 0; i < nums.length; i++) {
value += nums[i];
}
複製代碼
數組 nums
([1,2,3]) ,數組中的每一個數字的第一個值將被添加到 value
(0)。咱們遍歷數組並將其每一項添加到 value
。函數
讓咱們嘗試一下不一樣的方法來實現此功能:
const nums = [1, 2, 3];
const initialValue = 0;
const reducer = function (acc, item) {
return acc + item;
}
const total = nums.reduce(reducer, initialValue);
複製代碼
如今咱們有了相同的數組,但此次咱們不會改變初始值(即前段代碼中的 value
)。這裏,咱們有一個僅在開始時使用的初始值。接下來,咱們能夠建立一個函數,它接受一個累加器(acc
)和一個項(item
)。累加器是在上一次調用中返回的累積值(或者是 initialValue
),是下一個回調的輸入值。在這個例子中,你能夠把它想象成一個滾下一座山的雪球,當它以每個吃過的值的大小增加時,它會吃掉它路徑中的每一個值。
咱們將使用 .reduce()
來接收這個函數並從初始值開始。可使用箭頭函數簡寫:
const nums = [1, 2, 3];
const initialValue = 0;
const reducer = (acc, item) => {
return acc + item;
}
const total = nums.reduce(reducer, initialValue);
複製代碼
進一步縮短代碼長度,咱們知道箭頭函數,在沒有 {}
時,默認 return
;
const nums = [1, 2, 3];
const initialValue = 0;
const reducer = (acc, item) => acc + item;
const total = nums.reduce(reducer, initialValue);
複製代碼
如今咱們能夠在調用它的地方應用這個函數,也能夠直接設置初始值,以下:
const nums = [1, 2, 3];
const total = nums.reduce((acc, item) => acc + item, 0);
複製代碼
累加器多是一個使人生畏的術語,因此當咱們在回調調用上應用邏輯時,你能夠將它想象成數組的當前狀態。
若是不清楚發生了什麼,讓咱們記錄下每次迭代的狀況。reduce
使用的回調函數將針對數組中的每一個項運行。下面的演示將有助於更清楚地說明這一點。我使用了一個不一樣的數組([1,3,6]),由於數字與索引相同可能會使人困惑。
const nums = [1, 3, 6];
const reducer4 = function (acc, item) {
console.log(`Acc: ${acc}, Item: ${item}, Return value: ${acc + item}`);
return acc + item;
}
const total4 = nums.reduce(reducer4, 0);
複製代碼
當咱們執行這段代碼時,咱們會在控制檯看到如下輸出:
Acc: 0, Item: 1, Return value: 1
Acc: 1, Item: 3, Return value: 4
Acc: 4, Item: 6, Return value: 10
複製代碼
下面是一個更直觀的分解:
acc
)從初始值(initialValue
):0 開始的item
是1,因此返回值是1(0+1=1)acc
),item
(數組的第二項)是3item
是6既然咱們已經掌握了這一點,那麼讓咱們來看看 reducer
能夠作的一些常見和有用的事情。
假設您有一個數字數組,而且但願返回一個報告這些數字在數組中出現的次數的對象。請注意,這一樣適用於字符串。
const nums = [3, 5, 6, 82, 1, 4, 3, 5, 82];
const result = nums.reduce((tally, amt) => {
tally[amt] ? tally[amt]++ : tally[amt] = 1;
return tally;
}, {});
console.log(result);
//{ '1': 1, '3': 2, '4': 1, '5': 2, '6': 1, '82': 2 }
複製代碼
最初,咱們有一個數組和將要放入其中的對象。在 reducer
中,咱們首先判斷這個item是否存在於累加器中,若是是存在,加1。若是不存在,添加這一項並設置爲1。最後,請返回每一項出現的次數。而後,咱們運行reduce
函數,同時傳遞 reducer
和初始值。
假設咱們有一個數組,咱們但願基於一組條件建立一個對象。reduce
在這裏很是適用!如今,咱們但願從數組中任意一個數字項建立一個對象,並同時顯示該數字的奇數和偶數版本。
const nums = [3, 5, 6, 82, 1, 4, 3, 5, 82];
// we're going to make an object from an even and odd
// version of each instance of a number
const result = nums.reduce((acc, item) => {
acc[item] = {
odd: item % 2 ? item : item - 1,
even: item % 2 ? item + 1 : item
}
return acc;
}, {});
console.log(result);
複製代碼
控制檯輸出結果:
{ '1': { odd: 1, even: 2 },
'3': { odd: 3, even: 4 },
'4': { odd: 3, even: 4 },
'5': { odd: 5, even: 6 },
'6': { odd: 5, even: 6 },
'82': { odd: 81, even: 82 }
}
複製代碼
當咱們遍歷數組中的每一項時,咱們爲偶數和奇數建立一個屬性,而且基於一個帶模數運算符的內聯條件,咱們要麼存儲該數字,要麼將其遞增1。模算符很是適合這樣作,由於它能夠快速檢查偶數或奇數 —— 若是它能夠被2整除,它是偶數,若是不是,它是奇數。
在頂部,我提到了其餘一些便利的文章,這些文章有助於更熟悉 reducer
的做用。如下是個人最愛:
謝謝各位小夥伴願意花費寶貴的時間閱讀本文,若是本文給了您一點幫助或者是啓發,請不要吝嗇你的贊和Star,您的確定是我前進的最大動力。 github.com/YvetteLau/B…