Array Reduce JavaScript: Sintaks dan Contoh Penggunaan
reduce()
merupakan method array di JavaScript yang mengeksekusi fungsi callback pada setiap elemen array, nilai hasil kalkulasi pada elemen sebelumnya digunakan untuk melakukan kalkulasi pada elemen berikutnya.
Setelah menjalankan fungsi callback untuk semua elemen array, method ini menghasilkan nilai tunggal.
Kasus yang paling mudah dipahami adalah ketika kita ingin menjumlahkan semua elemen array angka.
Method ini memang terlihat agak rumit pada awalnya, tapi jangan khawatir karena ini akan kita pelajari secara perlahan mulai dari sintaks hingga contoh penggunaannya.
Sintaks
// arrow function
reduce((nilaiSebelumnya, nilaiSaatIni, indexSaatIni, array) => { ... }, nilaiAwal)
// callback function
reduce(callbackFn, nilaiAwal)
Parameter
-
callbackFn
: fungsi callback yang dieksekusi untuk setiap elemen array. Menerima empat argumen berikut:nilaiSebelumnya
: nilai yang dikembalikan dari fungsi callback sebelumnya.nilaiSaatIni
: nilai elemen array saat ini.indeksSaatIni
(opsional): indeks elemen saat ini.array
(opsional): array sumber.
-
nilaiAwal
(opsional):Jika ditentukan, nilai ini akan digunakan oleh
nilaiSebelumnya
saat pertama kali callback dipanggil, dannilaiSaatIni
akan berisi nilai elemen pertama pada array.Jika tidak,
nilaiSebelumnya
akan menggunakan elemen pertama array dannilaiSaatIni
menggunakan elemen kedua.
Nilai Kembalian
Mengembalikan nilai yang dihasilkan oleh fungsi callback sampai akhir elemen array.
Method ini dapat mengembalikan kesalahan TypeError
jika array tidak memiliki elemen dan nilaiAwal
tidak disediakan.
Cara Kerja reduce()
Mari kita gunakan array sederhana untuk memahami cara kerja reduce()
.
Untuk mengurangi distraksi, saya tidak akan membahas indeksSaatIni
dan array
karena indeksSaatIni
hanya diinisialisasi dengan indeks elemen saat ini yang sedang diiterasi/diulang.
Sedangkan array
diinisialisasi dengan array sumber.
Keduanya bersifat opsional, boleh kita hilangkan.
Yang terpenting adalah memahami nilai dari argumen nilaiSebelumnya
dan nilaiSaatIni
.
Tanpa nilaiAwal
Mari kita gunkaan contoh sederhana, dalam kasus kali ini kita akan menjumlahkan semua elemen pada array arrAngka
, tanpa nilaiAwal
.
const arrAngka = [1, 2, 3, 4, 5];
const result = arrAngka.reduce((nilaiSebelumnya, nilaiSaatIni) => {
return nilaiSebelumnya + nilaiSaatIni;
});
console.log(result); // 15
Dalam kasus ini fungsi callback dipanggil sebanyak empat kali, berikut langkah-langkahnya:
Pengulangan callback | nilaiSebelumnya | nilaiSaatIni | Nilai Kembalian |
---|---|---|---|
Pertama | 1 | 2 | 3 |
Kedua | 3 | 3 | 6 |
Ketiga | 6 | 4 | 10 |
Keempat | 10 | 5 | 15 |
Perhatikan gambar berikut.
Yang perlu diperhatikan di sini, ketika callback dipanggil pertama kali, nilai dari nilaiSebelumnya
akan menggunakan nilai dari elemen pertama array, 1
.
Sedangkan nilaiSaatIni
menggunakan nilai elemen kedua dari array, 2
.
Oleh karena itu, pada iterasi pertama fungsi callback menghasilkan nilai 3
hasil dari penjumlahan nilaiSebelumnya + nilaiSaatIni
(1 + 2
).
Karena masih ada elemen array, maka nilai ini tidak langsung dikembalikan, melainkan diinisialisasi ke nilaiSebelumnya
untuk pemanggilan callback berikutnya.
Jadi, pada pengulangan callback kedua, nilaiSebelumnya
sekarang bernilai 3
sedangkan nilaiSaatIni
bergeser menggunakan elemen array berikutnya yaitu 3
.
Singkatnya, tanpa nilaiAwal
:
Pada panggilan callback pertama,
nilaiSebelumnya
menggunakan nilai elemen pertam array, sedangkannilaiSaatIni
menggunakan elemen kedua.
Dengan nilaiAwal
Mari kita gunakan array yang sama, tapi sekarang kita inisialisasi nilaiAwal
dengan 5
.
const arrAngka = [1, 2, 3, 4, 5];
const result = arrAngka.reduce((nilaiSebelumnya, nilaiSaatIni) => {
return nilaiSebelumnya + nilaiSaatIni;
}, 5);
console.log(result); // 20
Dalam kasus kali ini fungsi callback dipanggil sebanyak lima kali, berikut langkah-langkahnya:
Pengulangan callback | nilaiSebelumnya | nilaiSaatIni | Nilai Kembalian |
---|---|---|---|
Pertama | 5 | 1 | 6 |
Kedua | 6 | 2 | 8 |
Ketiga | 8 | 3 | 11 |
Keempat | 11 | 4 | 15 |
Kelima | 15 | 5 | 20 |
Perhatikan gambar berikut.
Yang perlu diperhatikan di sini, nilai dari nilaiSebelumnya
tidak lagi menggunakan
elemen pertama array, melainkan nilai dari nilaiAwal
yaitu 5
.
Sedangkan nilaiSaatIni
menggunakan elemen pertama array. Oleh karena itu menghasilkan nilai 20
.
Selebihnya sama dengan contoh sebelumnya.
Jadi, dengan nilaiAwal
:
Pada panggilan callback pertama,
nilaiSebelumnya
menggunakan nilai darinilaiAwal
, sedangkannilaiSaatIni
menggunakan elemen pertama array.
Contoh
Menjumlahkan Nilai Objek Dalam Array
Mari kita gunakan contoh yang agak kompleks.
Kita di sini ingin mengetahui berapa total nilai mahasiswa jika dijumlahkan.
const mahasiswa = [
{ nama: 'ucup', nilai: 80 },
{ nama: 'budi', nilai: 90 },
{ nama: 'bambang', nilai: 75 },
];
const totalNilai = mahasiswa.reduce((nilaiSebelumnya, nilaiSaatIni) => {
return nilaiSebelumnya + nilaiSaatIni.nilai;
}, 0);
console.log(totalNilai); // 245
Kita disini perlu mengisi nilaiAwal
dengan 0
, kalau tidak, pada panggilan callback pertama, nilaiSebelumnya
akan diinisialisasi dengan elemen pertama pada array yaitu objek { nama: 'ucup', nilai: 80 }
.
Karena nilaiAwal
ditentukan, nilaiSaatIni
akan menggunakan elemen pertama pada array yaitu { nama: 'ucup', nilai: 80 }
.
Oleh karena itu di dalam badan fungsi kita perlu menggunakan notasi titik untuk mengakses nilai dari properti nilai
(nilaiSaatIni.nilai
).
Menyisipkan Objek ke Array
Saat membuat aplikasi kadang kita perlu mengatur ulang struktur array, tujuannya tentu saja agar lebih terstruktur.
Misalnya, ini array yang kita miliki sekarang.
['reza', 'ucup', 'udin'];
Di sini kita ingin memasukkan setiap elemen array ke dalam objek berisi properti name
untuk masing-masing elemen saat ini dan gender
kita isi dengan male
.
Jadi, ini yang kita inginkan.
[
{ name: 'reza', gender: 'male' },
{ name: 'ucup', gender: 'male' },
{ name: 'udin', gender: 'male' },
];
Masalah ini sebetulnya bisa diselesaikan dengan map
, tapi inilah jika kita menggunakan reduce
.
const usersMale = ['reza', 'ucup', 'udin'];
const refactUsersMale = usersMale.reduce((prev, user) => {
return [
...prev,
{
name: user,
gender: 'male',
},
];
}, []);
console.log(refactUsersMale);
/* output:
[
{ name: 'reza', gender: 'male' },
{ name: 'ucup', gender: 'male' },
{ name: 'udin', gender: 'male' }
]
*/
Contoh kali ini ada yang berbeda dari sebelumnya, kali ini nilaiAwal
disi dengan array kosong ([]
).
Ya, kita bisa mengisi nilaiAwal
dengan nilai apa pun termasuk angka, string, array, objek dan sebagainya.
...prev
(titik tiga) adalah sintaks spread, jika Anda belum mempelajarinya, jangan khawatir, Anda bisa kembali ke sini kapan saja.
Mengganti filter().map()
dengan reduce()
reduce
bisa kita gunakan sebagai pengganti filter().map()
yang lebih efisien.
Misalnya, kita memiliki array sebagai berikut.
[1, 2, 3, 4, 6];
Kita ingin memfilter bilangan genap ([2, 4, 6]
) lalu kita kalikan semuanya dengan 2
, sehingga hasilnya seperti ini.
[4, 8, 12];
Kita tidak bisa menangani kasus seperti ini hanya menggunakan map
, karena callback map harus mengembalikan nilai, kalau tidak, nilai undefined
dikembalikan.
Apalagi jika hanya menggunkan filter
, tidak bisa.
Mereka berdua saling melengkapi.
Jadi, inilah jika kita menggunakan filter().map()
.
const numbers = [1, 2, 3, 4, 6];
const result = numbers.filter((num) => num % 2 === 0).map((num) => num * 2);
console.log(result); // [ 4, 8, 12 ]
Tidak ada yang salah dengan metode di atas. Tapi, ini kurang efisien.
Perulangan atau callback dieksekusi sebanyak 8 kali, bukan 10 kali, apalagi 5 kali hanya karena elemennya ada 5.
5 kali untuk filter
, dan 3 kali untuk map
.
Kenapa map
hanya 3 kali? Karena filter
mengembalikan array berisi 3 elemen.
Kita bisa mengatasi ini dengan reduce
agar perulangan hanya dilakukan sebanyak 5 kali.
Jadi, inilah jika kita menggunakan reduce
.
const numbers = [1, 2, 3, 4, 6];
const result = numbers.reduce((prev, curr) => {
if (curr % 2 === 0) {
prev.push(curr * 2);
}
return prev;
}, []);
console.log(result); // [ 4, 8, 12 ]