Để hiểu tường tận và nhớ suốt đời bộ ba này, bạn phải dẹp ngay mấy cái định nghĩa học thuật khô khan đi. Hãy tưởng tượng bạn đang là một đầu bếp đứng trong căn bếp của mình, đối mặt với một rổ nguyên liệu mảng gốc: const roNguyenLieu = ['🥩', '🍗', '🥔', '🥕'];
Dưới đây là tấm bản đồ trực quan bằng hình ảnh và tư duy giúp bạn neo kiến thức này vào não vĩnh viễn.
1. map() — Nhà máy chế biến (Thay quần áo mới)
Bản chất tối thượng: Đầu vào có 4 phần tử, đầu ra bắt buộc phải có 4 phần tử. map() không bao giờ làm mất phần tử nào, nó chỉ biến đổi hình dạng của từng phần tử theo một công thức chung.
Hình ảnh nhớ lâu: Bạn mang rổ nguyên liệu đi NƯỚNG.
🥩 biến thành 🥩 nướng
- 🍗 biến thành 🍗 nướng
- Kết quả trả về: Một rổ đồ ăn chín gồm 4 món.
Cú pháp và cái bẫy return
Rất nhiều bạn mới học viết map như thế này và kết quả ra một mảng toàn undefined:
// CODE SAI (Thiếu return)
const doNuong = roNguyenLieu.map(item => {
item + '🔥';
}); // Kết quả: [undefined, undefined, undefined, undefined]Mẹo nhớ lâu: Đã mở ngoặc nhọn {} trong hàm thì BẮT BUỘC phải có từ khóa return. Nếu muốn viết tắt không cần return, hãy bỏ luôn dấu ngoặc nhọn!
// CODE ĐÚNG (Viết ngắn gọn - Implicit Return)
const doNuongGọn = roNguyenLieu.map(item => item + '🔥');
// Kết quả: ['🥩🔥', '🍗🔥', '🥔🔥', '🥕🔥']2. filter() — Người gác cổng (Lọc đồ đạt chuẩn)
- Bản chất tối thượng: Chạy qua từng phần tử, chấm điểm Đúng (true) hoặc Sai (false). Thằng nào được chấm true thì được copy sang mảng mới, thằng nào false bị vứt lại. Số lượng mảng mới luôn nhỏ hơn hoặc bằng mảng cũ.
- Hình ảnh nhớ lâu: Bạn là người ăn chay, bạn chỉ muốn lọc lấy RAU CỦ.
Hàm bên trong filter chỉ làm đúng một nhiệm vụ duy nhất: Trả về kết quả mang tính chất Đúng/Sai.
const danhSachSo = [1, 2, 3, 4, 5, 6];// Lọc số chẵn: Số nào chia hết cho 2 thì giữ lại
const soChan = danhSachSo.filter(num => num % 2 === 0);
console.log(soChan); // [2, 4, 6]
3. reduce() — Đút heo đất (Gom tất cả thành 1 cục)
Thằng này khó hiểu nhất vì cái tên của nó. reduce nghĩa là "giảm thu gọn". Nó sẽ ép một mảng nhiều phần tử thành đúng một giá trị duy nhất (có thể là 1 con số, 1 chuỗi, hoặc thậm chí là 1 Object tổng hợp).
Hình ảnh nhớ lâu (Trò chơi nuôi heo đất): *
accumulator(acc): Là con Heo đất của bạn.currentValue(curr): Là số Tiền bạn có mỗi ngày (từng phần tử trong mảng).initialValue: Là số tiền Vốn bạn bỏ sẵn vào heo từ ngày đầu tiên.
Giả sử bạn muốn tính tổng của mảng: const tienMoiNgay = [10, 20, 30]; và bạn bỏ vốn ban đầu vào heo là 0.
const tongTien = tienMoiNgay.reduce((heoDat, tienHomNay) => {
return heoDat + tienHomNay;
}, 0); // 0 chính là số vốn ban đầu bỏ vào heoDatHàm này sẽ chạy 3 vòng tương ứng với 3 phần tử:
- Vòng 1:
heoDatđang có 0đ.tienHomNaylà 10đ. Bạn lấy 0 + 10 = 10đ. Bạnreturn 10;tức là ôm con heo chứa 10đ này chuyền sang vòng sau. - Vòng 2:
heoDatnhận vào 10đ.tienHomNaylà 20đ. Bạn lấy 10 + 20 = 30đ. Bạn lạireturn 30;để chuyền con heo đi tiếp. - Vòng 3:
heoDatđang có 30đ.tienHomNaylà 30đ. Bạn lấy 30 + 30 = 60đ. Hết mảng! Kết quả cuối cùng bạn nhận được là con heo chứa60.
🔥 Lỗi chí mạng: Nếu bạn quên không viếtreturn heoDat + tienHomNay;ở trong hàm, thì ở vòng tiếp theo, con heo đất sẽ bị biến thànhundefined(rỗng tuếch) và code sẽ báo lỗi ngay lập tức. Bạn luôn luôn phải "chuyền heo đất" về cho vòng lặp kế tiếp.
💡 4 Tip Xương Máu Để Nhớ Lâu, Viết Code Cứng
item hay element một cách vô nghĩa. Hãy đặt tên theo quy tắc Mảng số nhiều -> Phần tử số ít.keywords.map(keyword => ...)posts.filter(post => ...)- Đọc lên như một câu tiếng Anh, não bạn sẽ tự động hiểu logic mà không cần cố nhớ.
- Cần mảng mới, kích thước y chang mảng cũ, chỉ đổi ruột? ➔ Dùng
map. - Cần mảng mới, lọc bớt phần tử đi theo điều kiện? ➔ Dùng
filter. - Cần tính toán gom về 1 kết quả duy nhất? ➔ Dùng
reduce.
reduce, hãy vẽ 2 cột: Cột Heo đất (acc) và cột Phần tử hiện tại (curr). Chạy tay thử 2 vòng là bạn sẽ tự khắc viết được code chuẩn mà không sợ bị loạn.