Menu

Higher-Order Function JavaScript: map, filter, reduce, dan Callback

Higher-order function di JavaScript: memberikan fungsi sebagai argumen, mengembalikan fungsi dari fungsi lain, dan pola map/filter/reduce yang akan kamu pakai setiap hari.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Fungsi Adalah Nilai

Di JavaScript, fungsi adalah nilai seperti nilai lainnya. Kamu bisa menyimpannya di variabel, memasukkannya ke array, memberikannya ke fungsi lain, atau mengembalikannya dari sebuah fungsi. Fakta itu saja sudah membuka satu gaya pemrograman tersendiri:

Begitu kamu terbiasa memperlakukan fungsi sebagai nilai, higher-order function tidak lagi terasa misterius. Higher-order function hanyalah fungsi yang menerima fungsi sebagai argumen, mengembalikan fungsi, atau keduanya. Itulah seluruh definisinya.

Menerima Fungsi sebagai Argumen

Bentuk yang paling umum: fungsi yang menerima callback dan menjalankannya untukmu. Kamu sudah memakainya tanpa memikirkannya.

forEach adalah higher-order: ia menerima fungsimu dan memanggilnya sekali untuk setiap item. setTimeout adalah higher-order: ia menerima fungsimu dan memanggilnya setelah jeda. Kamu fokus pada apa yang dilakukan; mereka mengurus kapan dan berapa kali.

Menulis versimu sendiri terlihat sama. Berikut fungsi kecil yang menjalankan callback hanya kalau sebuah kondisi bernilai true:

action adalah parameter yang kebetulan berisi fungsi. Memanggilnya dengan action() menjalankan apa pun yang diberikan.

Tiga yang Benar-Benar Akan Kamu Pakai: map, filter, reduce

Array dilengkapi method higher-order yang menggantikan sebagian besar loop for yang seharusnya kamu tulis. Kuasai ketiganya, dan banyak sekali kode sehari-hari jadi lebih pendek dan jelas.

map: mengubah setiap item

map memanggil fungsimu sekali untuk setiap item dan mengumpulkan nilai kembaliannya ke array baru. Panjangnya sama, isinya sudah diubah. Array aslinya tidak dimodifikasi.

filter: menyimpan yang cocok

filter menyimpan item yang membuat callback mengembalikan nilai truthy dan membuang sisanya. Nilai kembaliannya array baru, mungkin lebih pendek.

reduce: meringkas array menjadi satu nilai

reduce adalah yang serbaguna. Callback menerima akumulator yang terus berjalan dan item saat ini; apa pun yang kamu kembalikan menjadi akumulator berikutnya. Argumen kedua (di sini 0) adalah nilai awalnya.

Kamu bisa merangkainya. Di sinilah gaya ini terbayar:

Baca dari atas ke bawah: simpan pesanan yang sudah dibayar, ambil harganya, lalu jumlahkan. Tanpa loop, tanpa counter yang berubah-ubah, tanpa error selisih satu yang perlu dikhawatirkan.

Mengembalikan Fungsi dari Fungsi

Separuh lainnya dari higher-order. Fungsi yang membangun lalu mengembalikan fungsi lain:

multiplyBy(2) berjalan sekali dan menyerahkan fungsi yang benar-benar baru. Fungsi baru itu masih mengingat factor. Itulah closure, dan nanti ada halamannya sendiri. Untuk sekarang, pelajarannya: memanggil multiplyBy dengan argumen berbeda memberimu fungsi-fungsi khusus yang berbeda, dibangun dari templat yang sama.

Pola ini muncul di mana-mana:

Satu definisi, dua fungsi yang bisa dipakai ulang. Lebih baik daripada menulis warn dan info secara manual lalu menjaga keduanya tetap sinkron.

Fungsi Bernama vs Callback Inline

Kamu bisa memberikan arrow function langsung di tempat, atau memberikan fungsi lewat namanya. Keduanya berfungsi, pilih yang lebih enak dibaca:

Saat kamu memberikan isEven (tanpa kurung), kamu menyerahkan fungsinya sendiri. Menambahkan () akan langsung memanggilnya dan memberikan hasilnya, kesalahan umum para pemula:

nums.filter(isEven);     // correct: passes the function
nums.filter(isEven());   // wrong: calls isEven with no args, passes the result

Kalau callback-nya mulai melebar lebih dari beberapa baris, pisahkan dan beri nama. Kode di sekitarnya biasanya jadi lebih enak dibaca.

Contoh Lengkap

Higher-order function bersinar saat kamu menyusun potongan-potongan kecil. Misalkan kamu punya daftar produk dan ingin nama barang yang terjangkau dan tersedia, dalam huruf kapital:

Setiap helper punya satu tugas. Setiap method array melakukan satu transformasi. Pipeline-nya terbaca seperti spesifikasi tentang apa yang kamu mau, bukan penjelasan tentang cara melakukan perulangan.

Kapan Tidak Memakainya

Method higher-order memang hebat, tetapi bukan pengganti loop untuk setiap situasi:

  • Kalau kamu perlu berhenti di tengah jalan, for atau for...of dengan break lebih jelas daripada mencoba keluar dari forEach.
  • Kalau kamu melakukan sesuatu yang async di dalam callback, map dan forEach tidak akan menunggunya. Pakai for...of dengan await, atau Promise.all dengan map.
  • Kalau callback-nya mengubah state bersama, kamu mulai menjauh dari keunggulan gaya ini. Pakai loop biasa atau refactor agar mengembalikan nilai baru.

Kalau dipakai di tempat yang tepat, map, filter, dan reduce memangkas sebagian besar boilerplate loop dari kode sehari-hari. Kalau dipakai di mana-mana, keterbacaan justru menurun. Pilih alat yang membuat maksudmu paling jelas.

Berikutnya: Objek

Fungsi bukan satu-satunya nilai yang layak dijadikan fondasi. Objek adalah andalan JavaScript untuk mengelompokkan data dan perilaku yang saling berkaitan, dan objek jugalah yang mengisi sebagian besar array yang baru saja kamu filter dan map. Itu topik halaman berikutnya.

Pertanyaan yang sering diajukan

Apa itu higher-order function di JavaScript?

Higher-order function adalah fungsi yang melakukan setidaknya satu dari dua hal: menerima fungsi lain sebagai argumen, atau mengembalikan fungsi sebagai hasilnya. Array.prototype.map, setTimeout, dan addEventListener semuanya higher-order: ketiganya menerima callback dan menjalankannya untukmu.

Apa bedanya map, filter, dan reduce?

map mengubah setiap item dan mengembalikan array baru dengan panjang yang sama. filter menyimpan item yang membuat callback mengembalikan nilai truthy dan mengembalikan array (yang mungkin lebih pendek). reduce meringkas array menjadi satu nilai dengan menggabungkan item satu per satu. Ketiganya adalah higher-order function yang menerima callback.

Mengapa kita mengembalikan fungsi dari fungsi lain?

Untuk membangun helper kecil yang bisa dikonfigurasi tanpa mengulang logika. Fungsi seperti multiplyBy(n) mengembalikan fungsi baru yang mengalikan dengan n, jadi multiplyBy(2) dan multiplyBy(10) memberimu dua fungsi khusus dari satu definisi. Pola ini memakai closure dan umum ditemukan di event handler, middleware, dan library utilitas.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai