Pada chapter Callbacks di section Functions, Budi sudah mengirim function ke function lain: daftar tugas diproses oleh satu function yang memanggil ulang function yang dikirimkan padanya. Saat itu, pemakaian itu terasa seperti trik khusus. Padahal yang sedang bekerja adalah salah satu ciri utama JavaScript: function diperlakukan seperti nilai biasa — bisa disimpan di variabel, dikirim sebagai argumen, dan dikembalikan dari function lain.
Function yang menerima function sebagai argumen, atau mengembalikan function baru, disebut higher-order function. Konsep ini adalah motor penggerak paradigma functional di JavaScript: map dan filter di section Arrays bekerja karena sifat ini, dan pola-pola di chapter selanjutnya — composition, memoization, currying — dibangun di atasnya. Sebagian besar pengalaman kita sejauh ini sebenarnya sudah melibatkan higher-order function; chapter ini hanya membongkar penutupnya, lalu menulis satu dari nol.
Function adalah Nilai #
Sebelum menyebut istilahnya, mari kita pastikan fondasinya. Pernyataan function tidak wajib menyebut nama; hasilnya adalah nilai seperti angka atau string, hanya saja nilai ini bisa dipanggil. Karena itu function boleh dijadikan argumen, dan parameter yang menerimanya hanyalah variabel biasa yang kebetulan memegang function:
const dobel = function (angka) {
return angka * 2;
};
console.log(dobel(7));
console.log(typeof dobel);Output yang Dihasilkan:
14
functiontypeof menjawab "function" — tipe miliknya sendiri, tetapi perilakunya sebagai nilai sama seperti lainnya: ia disimpan, dikirim, dan dikembalikan. Arrow function dari section Functions mempersingkat penulisannya, dan bentuk itulah yang dipakai sepanjang chapter ini.
Cara termudah membaca higher-order function: callback adalah titik penyisipan perilaku. Pemilik function sudah menyiapkan kerangka kerjanya — menelusuri elemen, mengumpulkan hasil — dan detail “apa yang dilakukan pada setiap elemen” disisipkan lewat argumen. Kerangka yang sama bisa menerima ratusan perilaku berbeda tanpa diubah satu baris pun.
map dan filter sebagai Higher-Order Function #
Dua method yang selama ini kita pakai ternyata memenuhi definisi tadi. map menerima callback lalu memanggilnya untuk setiap elemen; filter menerima callback yang bertugas sebagai uji. Keduanya tidak peduli isi callbacknya — yang mereka butuhkan adalah sebuah function:
// pembuat-fungsi.js
// Higher-order function: menerima function, mengembalikan function.
// --- 1. map dan filter: HOF yang menerima callback ---
const hargaMenu = [12000, 18000, 8000, 24000];
const hargaDenganPajak = hargaMenu.map((harga) => harga + (harga * 10) / 100);
console.log(hargaDenganPajak);
const hargaTerjangkau = hargaMenu.filter((harga) => harga <= 15000);
console.log(hargaTerjangkau);
// --- 2. menulis HOF sendiri: function sebagai parameter ---
function terapkanKeSemua(daftar, operasi) {
const hasil = [];
for (const nilai of daftar) {
hasil.push(operasi(nilai));
}
return hasil;
}
console.log(terapkanKeSemua(hargaMenu, (harga) => harga * 2));
// --- 3. function builder: mengembalikan function baru ---
function buatPengali(faktor) {
return function (angka) {
return angka * faktor;
};
}
const kalikanDua = buatPengali(2);
const kalikanSepuluh = buatPengali(10);
console.log(kalikanDua(21));
console.log(kalikanSepuluh(21));
// --- 4. builder dipakai sebagai callback: filter yang bisa diatur ---
function buatFilterMaksimal(batas) {
return function (angka) {
return angka <= batas;
};
}
const diBawahSedang = buatFilterMaksimal(15000);
console.log(hargaMenu.filter(diBawahSedang));
console.log(hargaMenu.filter(buatFilterMaksimal(10000)));Output yang Dihasilkan:
[ 13200, 19800, 8800, 26400 ]
[ 12000, 8000 ]
[ 24000, 36000, 16000, 48000 ]
42
210
[ 12000, 8000 ]
[ 8000 ]Mari kita telaah baris-baris pentingnya:
- Baris 7 (
hargaMenu.map(...)):mapmenerima callback(harga) => harga + (harga * 10) / 100dan memanggilnya sekali per elemen. Kembalian callback dikumpulkan menjadi array baru[ 13200, 19800, 8800, 26400 ]— perhitungan pajak dititipkan ke function yang dikirim. - Baris 10 (
hargaMenu.filter(...)):filtermemakai callback-nya sebagai uji benar-salah; hanya12000dan8000yang lolos syarat<= 15000. - Baris 14–20 (
terapkanKeSemua): inilah higher-order function versi kita sendiri. Parameteroperasihanyalah variabel biasa yang memegang function, dan baris 17 memanggilnya denganoperasi(nilai)— persis seperti yang dilakukanmap. Kode ini menyingkap mekanisme di balik layar:maptidak melakukan apa pun di luar memanggil function yang dikirim. - Baris 22 (pemanggilan HOF): callback
(harga) => harga * 2dikirim sebagai argumen kedua, dan hasilnya[ 24000, 36000, 16000, 48000 ]— setiap harga digandakan. - Baris 25–29 (
buatPengali): higher-order function jenis kedua — yang mengembalikan function. Function dalam menutup parameterfaktordari function luarnya, mekanisme closure dari section Functions. - Baris 31–34 (dua turunan):
kalikanDuadankalikanSepuluhlahir dari template yang sama, tetapi masing-masing membawa nilaifaktoryang berbeda:42dan210untuk masukan21. - Baris 37–45 (builder sebagai callback):
buatFilterMaksimalmenggabungkan dua arah sekaligus — ia dikembalikan sebagai function, lalu dikirim kefiltersebagai callback. Batas15000menghasilkan dua harga, batas10000hanya satu.
Sebagai tambahan, callback dari map sebenarnya menerima lebih dari satu argumen: nilai, index, dan array asalnya. Selama ini kita hanya memakai yang pertama, tetapi argumen kedua berguna saat posisi elemen ikut menentukan hasil:
const labelHarga = hargaMenu.map((harga, urutan) => `${urutan + 1}. Rp${harga}`);
console.log(labelHarga[0]);
console.log(labelHarga.length);Output yang Dihasilkan:
1. Rp12000
4Callback dua parameter itu tetap satu function biasa — map tinggal mengisi urutan dengan posisi elemen yang sedang diproses.
Function Builder: Function yang Dikonfigurasi Sekali #
Baris 31–45 memperlihatkan pola yang patut diberi nama: function builder — function yang tugasnya membuat function lain dengan konfigurasi yang sudah terpasang. Nama pemanggilnya biasa diawali buat..., dan isi yang berbeda-beda (faktor, batas) dikunci sejak saat pembuatan, bukan saat pemanggilan:
function buatPenyapa(sapaan) {
return (nama) => sapaan + ", " + nama + "!";
}
const sapaKasir = buatPenyapa("Selamat pagi");
console.log(sapaKasir("Budi"));
console.log(sapaKasir("Siti"));Output yang Dihasilkan:
Selamat pagi, Budi!
Selamat pagi, Siti!Perhatikan bahwa builder tidak mengulang logika — sapaKasir dipanggil dua kali dengan sapaan yang sama, karena konfigurasi sapaan hanya ditulis sekali. Pola factory ini kita temui lebih dulu di chapter Closures; bedanya sekarang, kita membacanya sebagai higher-order function: function yang kembaliannya adalah function.
Builder semacam ini juga menyimpan konfigurasi tanpa variabel global. Nilai sapaan hidup di closure milik sapaKasir, sehingga dua builder dengan konfigurasi berbeda bisa hidup berdampingan tanpa saling menimpa — keuntungan yang sama yang diperlihatkan dua penghitung pada chapter Closures.
Kapan Function Biasa, Kapan Builder #
Dua bentuk pada berkas contoh mengajak sebuah pertimbangan praktis. Function biasa seperti terapkanKeSemua menjawab kebutuhan “lakukan X pada semua item”, dengan perilaku ditentukan pemanggil saat pemanggilan. Builder seperti buatFilterMaksimal menjawab kebutuhan “sediakan versi X yang sudah dikonfigurasi”, dengan perilaku dikunci sejak pembuatan.
Kaidah pemilihannya mengikuti frekuensi. Bila konfigurasi dipakai sekali, function biasa cukup — builder hanya menambah lapisan tanpa keuntungan. Bila konfigurasi yang sama dipakai di banyak tempat, builder menghasilkan nama bernama seperti hargaMember atau diBawahSedang, dan perubahan konfigurasi cukup terjadi di satu tempat pembuatannya. Pada pemakaian nyata, keduanya sering bekerja bersama: builder menyiapkan function, lalu higher-order function seperti map dan filter menjalankannya atas data — susunan yang persis kita rangkai di chapter berikutnya.
Satu function yang bisa menerima function lain membuka pintu berikutnya: memasang beberapa function kecil menjadi satu alur kerja. Itulah function composition yang dibahas di chapter selanjutnya.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
pembuat-fungsi.js
Unduh berkas// pembuat-fungsi.js
// Higher-order function: menerima function, mengembalikan function.
// --- 1. map dan filter: HOF yang menerima callback ---
const hargaMenu = [12000, 18000, 8000, 24000];
const hargaDenganPajak = hargaMenu.map((harga) => harga + (harga * 10) / 100);
console.log(hargaDenganPajak);
const hargaTerjangkau = hargaMenu.filter((harga) => harga <= 15000);
console.log(hargaTerjangkau);
// --- 2. menulis HOF sendiri: function sebagai parameter ---
function terapkanKeSemua(daftar, operasi) {
const hasil = [];
for (const nilai of daftar) {
hasil.push(operasi(nilai));
}
return hasil;
}
console.log(terapkanKeSemua(hargaMenu, (harga) => harga * 2));
// --- 3. function builder: mengembalikan function baru ---
function buatPengali(faktor) {
return function (angka) {
return angka * faktor;
};
}
const kalikanDua = buatPengali(2);
const kalikanSepuluh = buatPengali(10);
console.log(kalikanDua(21));
console.log(kalikanSepuluh(21));
// --- 4. builder dipakai sebagai callback: filter yang bisa diatur ---
function buatFilterMaksimal(batas) {
return function (angka) {
return angka <= batas;
};
}
const diBawahSedang = buatFilterMaksimal(15000);
console.log(hargaMenu.filter(diBawahSedang));
console.log(hargaMenu.filter(buatFilterMaksimal(10000)));