Function adalah unit pengemasan logika yang paling dasar: satu blok kode bernama yang menerima masukan, mengolahnya, dan mengembalikan hasil. Di Node.js, function memegang peran jauh lebih besar daripada sekadar organisasi kode — function adalah warga kelas satu (first-class citizen) yang bisa disimpan ke variabel, dikirim sebagai argumen, dan dikembalikan dari function lain, sehingga seluruh pola asynchronous Node.js berdiri di atasnya. Pada chapter ini kita akan membandingkan tiga bentuk penulisan function, mengupas perilaku kata kunci this yang membedakan arrow function dari function biasa, lalu memakai default parameter dan rest parameter untuk membuat function yang lentur.
Tiga Bentuk Function #
JavaScript menyediakan tiga cara membuat function, dan ketiganya masih kita temui di kode Node.js masa kini. Function declaration adalah bentuk klasik dengan kata kunci function; function expression menempatkan function sebagai nilai yang disimpan ke variabel; arrow function adalah sintaks ringkas sejak ES 2015. Perbedaan teknis terpenting antara declaration dan dua bentuk lainnya ada pada hoisting — persis seperti yang kita lihat pada Chapter Variabel dan Scope. Simpan berikut sebagai bentuk-function.mjs:
// Function declaration diangkat (hoisted), jadi bisa dipanggil lebih dulu
console.log(`luas persegi 4x4 : ${luasPersegi(4)}`);
function luasPersegi(sisi) {
return sisi * sisi;
}
// Function expression: nilainya baru tersedia setelah baris ini
const konversiSuhu = function (celsius) {
return celsius * 1.8 + 32;
};
// Arrow function untuk operasi ringkas
const sapa = (nama) => `Halo, ${nama}! Selamat belajar.`;
console.log(`100 C dalam F : ${konversiSuhu(100)}`);
console.log(sapa("Budi"));Output yang Dihasilkan:
luas persegi 4x4 : 16
100 C dalam F : 212
Halo, Budi! Selamat belajar.Mari kita telaah baris-baris kode di atas:
- Baris 2-3:
luasPersegi(4)dipanggil sebelum barisfunction luasPersegidieksekusi. Pemanggilan ini berhasil karena function declaration diangkat beserta isinya ke awal scope. - Baris 10 (
const konversiSuhu = function ...): function expression mengikuti aturanconst— baru bisa dipakai setelah baris deklarasinya berjalan, dan tidak bisa dipanggil lebih dulu. - Baris 15 (
const sapa = (nama) => ...): arrow function satu ekspresi tidak butuh kurung kurawal maupunreturn; nilai ekspresi langsung menjadi hasil function. Untuk badan lebih dari satu baris, kita tetap menulis{ ... return ... }.
Arrow Function dan Kata Kunci this #
Perbedaan paling substansial arrow function bukan penulisan yang pendek, melainkan cara this diperlakukan. Function biasa mendefinisikan this sendiri setiap kali dipanggil: ketika dipanggil sebagai method tugas.ringkasReguler(), nilai this menunjuk object tugas. Arrow function tidak memiliki this sendiri — arrow function meminjam this dari scope tempat arrow function ditulis, apa pun cara pemanggilannya. Berkas arrow-this.mjs memperlihatkan akibatnya:
const tugas = {
judul: "Belajar Node.js",
durasiJam: 2,
// Method biasa: this menunjuk object pemilik method
ringkasReguler() {
return `${this.judul} (${this.durasiJam} jam)`;
},
// Arrow function: tidak punya this sendiri,
// this diambil dari scope luar (module scope, bernilai undefined)
ringkasArrow: () => {
return `${this.judul} (${this.durasiJam} jam)`;
},
};
console.log(tugas.ringkasReguler());
try {
console.log(tugas.ringkasArrow());
} catch (e) {
console.log(`${e.name}: ${e.message}`);
}Output yang Dihasilkan:
Belajar Node.js (2 jam)
TypeError: Cannot read properties of undefined (reading 'judul')Penjelasan kedua hasilnya:
ringkasReguler()mengembalikan ringkasan dengan benar. Ekspresi pemanggilan berbentukobject.method(), sehinggathisdi dalam method menunjuk objecttugasdanthis.judulterbaca.ringkasArrow()melemparTypeErrorkarenathisdi dalam arrow function tidak menunjuktugas, melainkan diambil dari scope luar — scope module. Pada berkas.mjs,thislevel module bernilaiundefined, sehinggathis.judulsama dengan membaca property dariundefined.
Parameter Bawaan dan Rest Parameter #
Function modern JavaScript punya dua fitur parameter yang menggantikan trik lama seperti argumen || nilaiBawaan. Default parameter mengisi nilai cadangan ketika argumen yang masuk bernilai undefined, sedangkan rest parameter menampung sisa argumen menjadi array sungguhan. Keduanya dirangkum dalam parameter.mjs:
// Default parameter: dipakai bila argumen bernilai undefined
function buatSambutan(nama, salam = "Selamat datang") {
return `${salam}, ${nama}!`;
}
// Rest parameter: kumpulkan sisa argumen menjadi array
function hitungTotal(...angka) {
let total = 0;
for (let i = 0; i < angka.length; i++) {
total += angka[i];
}
return total;
}
// Kombinasi: parameter biasa di depan, rest di belakang
function catatLog(level, ...pesan) {
return `[${level}] ${pesan.join(" ")}`;
}
console.log(buatSambutan("Budi"));
console.log(buatSambutan("Siti", "Selamat pagi"));
console.log(`total : ${hitungTotal(1500, 2000, 500)}`);
console.log(catatLog("info", "server", "menyala", "di port 3000"));Output yang Dihasilkan:
Selamat datang, Budi!
Selamat pagi, Siti!
total : 4000
[info] server menyala di port 3000Mari kita bedah perilakunya:
- Baris 23 (
buatSambutan("Budi")): argumen kedua tidak dikirim, jadisalamterisi default"Selamat datang". Pemanggilan kedua mengirim"Selamat pagi"sehingga default diabaikan. - Baris 9 (
...angka): tiga argumen1500, 2000, 500terkumpul menjadi array[1500, 2000, 500]di dalam function, lalu dijumlahkan dengan loop biasa. - Baris 17 (
catatLog): parameterlevelmenangkap argumen pertama, sisanya masukpesan. Methodjoin(" ")merangkai array menjadi satu kalimat. Perhatikan bahwa rest parameter harus selalu berada di posisi terakhir.
Function sebagai Nilai #
Karena function adalah nilai, function bisa dikirim sebagai argumen ke function lain — function yang menerima function seperti ini disebut higher-order function, dan function yang dikirim disebut callback. Pola inilah yang dipakai hampir seluruh API Node.js, dari pembacaan berkas hingga penanganan request HTTP. Versi paling sederhananya terlihat seperti ini:
function jalankanTugas(nama, selesai) {
console.log(`menjalankan ${nama}...`);
selesai(`tugas ${nama} selesai`);
}
jalankanTugas("backup", function (hasil) {
console.log(`callback: ${hasil}`);
});Output yang Dihasilkan:
menjalankan backup...
callback: tugas backup selesaiFunction jalankanTugas menerima dua argumen: string nama dan function selesai. Di dalam badannya, jalankanTugas memutuskan kapan callback dipanggil — di sini tepat setelah pesan “menjalankan” dicetak. Pemanggilan selesai(...) menjalankan function anonim yang kita kirim, dan hasilnya dicetak dari dalam callback. Pada kode nyata Node.js, callback seperti ini dijalankan setelah operasi lambat selesai, bukan seketika; mekanisme penjadwalannya akan kita bahas tuntas pada Section Asynchronous Runtime.
Referensi lanjutan untuk topik chapter ini:
Kita kini bisa menulis function dalam tiga bentuk dan memilih bentuk yang tepat untuk konteksnya. Seiring aplikasi tumbuh, function menerima semakin banyak data terstruktur sebagai masukan — object. Chapter berikutnya, Object dan Destructuring, memperkenalkan cara membaca dan membentuk object yang ringkas serta aman.