Cá nhân mình thấy method reduce()
trong JS được ứng dụng rất nhiều, và nói thật cá nhân mình lúc mới tìm hiểu reduce
thấy khá vất vả, search trên mạng khá nhiều rồi mới thấm được ít. Chính vì lẽ đó hôm này mình sẽ viết một bài dựa trên hiểu biết (đã tìm hiểu cộng với áp dụng) cộng thêm với dịch thuật từ một số trang web uy tín về JS để giải thích rõ hơn về method reduce()
cũng như các (cách) ứng dụng của nó nhé. Oke, let’s go.
Khi hiểu rõ bản chất một thứ gì rồi, thì các vấn đề liên quan tới nó sẽ tự nhiên biến mất. Người ta sợ hãi những thứ họ không hiểu và lãng tránh nó để rồi mất một cơ hội để … “làm quen”. Lang man là vậy đó. Nhập đề ăn rơ lại nhé. Cú pháp của method reduce
này như sau:
arr.reduce(callback, initialValue);
Thuật ngữ cơ bản
Tìm hiểu reduce()
thì các bạn sẽ thấy có 2 thuật ngữ:
reducer
(thực ra là một callback, tham số đầu tiên của hàmreduce
)accumulator
(biến cộng dồn, tham số đầu tiên của callback reducer).
Bạn tưởng tượng nhé reduce nó giống như một cái vòng lặp, ví dụ mảng [1, 2, 3, 4, ..., 10]
nó sẽ lặp (từ trái lần lần sang phải) đến hết mảng (1 -> 10). Với mỗi lần lặp, reduce sẽ gọi callback reducer.
Reducer và các tham số
Callback reducer nhận hai tham số (thực tế 4 nhưng phạm vi bài viết chúng ta tìm hiểu 2 tham số quan trọng nhất):
accumulator
- biến cộng dồn nói phía trêncurrentItem
- giá trị hiện tại đang lặp
Và chỉ trả về duy nhất một giá trị. Giá trị này sẽ được truyền vào tham số accumulator
của callback reducer ở lần gọi tiếp theo, nếu hết vòng lặp (không gọi reducer nữa) thì trả về giá trị này.
Ví dụ 1:
1 | var array = [1, 2, 3, 4, 5]; |
Ví dụ 2:
1 | var array = [9, 2, 3, 4, 5]; |
Ví dụ 3:
1 | var array = [9, 2, 3, 4, 5]; |
initialValue - giá trị khởi tạo
Giá trị khởi tạo cho callback reducer, giá trị này được truyền lúc gọi callback.
Khi gọi callback reducer mà bản thân cái mảng không có phần tử nào cộng với việc không có initialValue
thì sẽ bị lỗi
1 | var array = []; |
Ứng dụng của reduce
1 | var value = 0; |
Kết quả in ra là 30
.
Hàm này với mỗi lần lặp sẽ thay đổi giá trị biến value
. Nhìn chung cách cũng ổn cơ mà xét về mặt pure function thì nó đã tác động đến biến (value
) bên ngoài phạm vi vòng lặp. Nên để tránh ảnh hưởng đến biến value
ta sẽ sử dụng reduce()
. Kết quả in ra sẽ tương tự nhau.
Cách dùng reduce sẽ như vầy:
1 | /* giá trị mặc định đầu tiên cho nó, giống value phía trên, giá trị mặc định đầu tiên là 0 */ |
Code ở trên rất đơn giản không có phức tạp cho lắm, lúc này bạn mở developer tool ra check xem console.log
trong reducer
in ra cái gì nhé.
Nó sẽ in ra như thế này.

Chúng ta sẽ đi phân tích chút xíu về cơ chế chạy chỗ này, mình sẽ mô phỏng 4 bước của quá trình chạy nhé:
- Vì mảng có 3 phần tử, nó sẽ chạy 3 lần. Ở lần chạy đầu tiên
accumulator
sẽ có giá trị là0
, giá trị này là từinitialValue
truyền vào thông qua methodreduce
. VàcurrentItem
lúc này là5
sẽ cộng vớiaccumulator
(accumulator
lúc này là0
), return ra5
kết quả return của reducer sẽ “tự động cộng dồn” vàoaccumulator
(thực ra cơ chế là nó lấy giá trị return này pass vào tham sốreducer
lần nữa). - Lần 2
accumulator
đang có giá trị là5
(kết quả từ bước 1), cộng vớicurrentItem
lúc này là10
, return về 15. - Lần chạy cuối cùng tương tự bước 2,
currentItem
lúc này là15
cộng vớiaccumulator
giá trị là15
return về30
. - Vì đã hết mảng nên return giá trị
accumulator
về.
Đó là ví dụ đơn giản về reduce. Và sau đây mình sẽ nâng cao lên một chút.
Nâng cao chút - Ứng dụng reduce với array (flatten array)
Ví dụ này từ bài viết của mình
Ứng dụng reduce vào flatten mảngMình có mảng như sau:
1 | var arr = [ 1, 2, 3, [ 1, 2, 3, 4, [ 2, 3, 4 ] ] ]; |
Và nếu JS trao cho mình cơ hội được viết lại hàm .flat
thì mình sẽ dùng viết lại như ri:
1 | function flatArray(arr) { |
Dùng như sau:
1 | var flatten = flatArray(arr); |
Oke, xong ví dụ đơn gian thứ hai rồi nha.
Ứng dụng reduce với re-structure object
Giả sử mình có object như thế này:
1 | var usersInfo = [ |
Và mình muốn nó re-structure lại như vầy:
1 | var usersInfo = { |
Vậy ứng dụng reduce
mình sẽ làm như thế nào nhỉ? Các bạn suy nghĩ chứ khoan kéo xuống phần mình làm nha. 3 phút nghĩ suy bắt đầu.
Đây là phần mình giải quyết:
1 | var objectMapFromArray = (arr) => arr.reduce((accumulator, currentItem) => { |
Gọi sử dụng:
1 | objectMapFromArray(usersInfo); |
Và đây là kết quả:

Summary
Qua bài ni, mình hi vọng bạn đã hiểu cách thức hàm này hoạt động. Oh yeah.
Updated date: 21.03.2020