Argumen yang tidak diberi nilai memicu bug yang sulit terlihat, karena perhitungan tetap berjalan dengan undefined di dalamnya tanpa memunculkan error. Topik ini membahas dua fitur parameter yang menutup masalah semacam itu, yaitu nilai default untuk mengisi argumen kosong dan rest parameter untuk mengumpulkan argumen sisa menjadi array. Istilah rest mengacu pada sisa argumen yang tidak terpetakan ke parameter mana pun, dan penulisannya hanya tiga titik di depan nama parameter. Setelah membacanya, fungsi dapat ditulis dengan nilai cadangan yang masuk akal, dan parameter wajib dapat dipaksakan lewat pesan error yang jelas. Fungsi dengan jumlah argumen yang tidak pasti pun dapat dihadapi tanpa trik tambahan.
Nilai default parameter#
Nilai default adalah ekspresi yang dipasangkan dengan parameter menggunakan tanda sama dengan, dan ekspresi itu dipakai bila argumen yang bersangkutan tidak diberikan atau diberikan dengan nilai undefined. Pada definisi salam(nama = "tamu"), pemanggilan tanpa argumen tetap menghasilkan sapaan yang utuh karena parameter nama terisi nilainya. Fungsi dengan default biasanya lebih pendek daripada versi yang memeriksa undefined secara manual di dalam tubuhnya, dan semua pemanggilnya otomatis mendapat perlakuan yang sama.
Berkas berikut memanggil fungsi yang sama dengan tiga cara, lengkap, tanpa argumen, dan dengan undefined.
// Nilai default dipakai bila argumen tidak diberi nilai atau bernilai undefined.
function salam(nama = "tamu") {
return "Selamat datang, " + nama + "!";
}
console.log(salam("Citra"));
console.log(salam());
console.log(salam(undefined));Selamat datang, Citra!
Selamat datang, tamu!
Selamat datang, tamu!Dua baris terakhir menghasilkan keluaran yang sama, karena undefined memang menjadi tanda bahwa argumennya kosong. Nilai lain tidak demikian, pemanggilan salam(null) menghasilkan “Selamat datang, null!”, karena null dianggap sebagai nilai yang sengaja diberikan dan default tidak diaktifkan. Perbedaan ini penting saat membaca kode yang menyeret nilai dari sumber luar, undefined dan tidak terisi memang berpasangan, sedangkan nilai lain diperlakukan apa adanya.
Default dievaluasi saat pemanggilan#
Ekspresi default tidak dihitung sekali saat fungsi didefinisikan, melainkan dievaluasi setiap kali fungsi dipanggil dengan argumen yang kosong. Karena itu ekspresinya boleh berupa apa saja, termasuk pemanggilan fungsi lain, dan boleh merujuk parameter yang terletak sebelum dirinya. Sifat inilah yang memungkinkan satu pola penting, yaitu parameter wajib yang memunculkan error bila tidak diisi.
Berkas berikut memakai fungsi bantu bernama wajib sebagai default parameter pembagi.
// Default dievaluasi setiap pemanggilan, dan nilainya boleh berupa fungsi.
function wajib(namaParameter) {
throw new Error("parameter " + namaParameter + " wajib diisi");
}
function bagi(angka, pembagi = wajib("pembagi")) {
return angka / pembagi;
}
console.log(bagi(84, 2));
try {
console.log(bagi(84));
} catch (error) {
console.log("error:", error.message);
}42
error: parameter pembagi wajib diisiPada pemanggilan bagi(84, 2), fungsi wajib tidak pernah berjalan karena pembagi sudah terisi, sedangkan pada bagi(84) evaluasi default memanggil wajib dan errornya terlempar dengan pesan yang menyebut nama parameternya. Pola ini mengubah kelalaian pemanggil menjadi pesan yang tepat sasaran, jauh lebih mudah ditelusuri daripada hasil NaN yang merambat diam-diam. Default juga dapat merujuk parameter di depannya seperti pada contoh berikut.
function hargaAkhir(nominal, diskonPersen = 10) {
return nominal - nominal * (diskonPersen / 100);
}
console.log(hargaAkhir(200000));
console.log(hargaAkhir(200000, 25));180000
150000Fungsi hargaAkhir memakai diskon 10 persen sebagai nilai lazim, sehingga pemanggilan tanpa argumen kedua menghasilkan 180000 dari nominal 200000. Pemanggilan dengan diskon 25 persen mengabaikan default dan menghasilkan 150000. Urutan parameternya penting, default hanya dapat merujuk parameter yang terletak di depannya, tidak sebaliknya.
Rest parameter#
Fungsi yang jumlah argumennya tidak pasti, misalnya menghitung rata-rata dari sejumlah nilai, ditangani dengan rest parameter. Penulisannya tanda tiga titik di depan nama parameter terakhir, dan parameter itu mengumpulkan seluruh argumen sisa menjadi satu array sungguhan yang bisa diindeks, dihitung length-nya, dan diiterasi. Parameter tetap di depannya menerima argumen seperti biasa, sehingga satu fungsi dapat memadukan parameter tetap dan parameter sisa.
Berkas berikut memuat fungsi rata-rata yang menerima sejumlah nilai bebas dan fungsi pencatat yang memadukan keduanya.
// Rest parameter mengumpulkan argumen sisanya menjadi array sungguhan.
function rataRata(...nilai) {
let jumlah = 0;
for (const n of nilai) {
jumlah += n;
}
return jumlah / nilai.length;
}
console.log(rataRata(80, 72, 95, 68, 90));
console.log(rataRata(10, 20));
function catat(status, ...pesan) {
return { status, jumlahPesan: pesan.length };
}
console.log(catat("OK", "cache dibersihkan", "indeks diperbarui"));81
15
{ status: 'OK', jumlahPesan: 2 }Fungsi rataRata menghitung 405 dibagi lima menjadi 81 pada pemanggilan pertama dan 30 dibagi dua menjadi 15 pada pemanggilan kedua, tanpa mengubah satu baris pun di tubuhnya. Fungsi catat menunjukkan pemaduan parameternya, argumen pertama mengisi status, sedangkan dua argumen berikutnya terkumpul di array pesan.
Bentuk yang melanggar aturan itu tampak seperti berikut. Potongan ini sengaja tidak dijalankan karena error sintaksnya membuat seluruh berkas gagal dimuat.
// tidak-dijalankan
function rusak(...nilai, terakhir) {
return nilai.length + terakhir;
}Kontras dengan arguments#
Sebelum rest parameter ada, setiap fungsi biasa membawa object bernama arguments yang berisi seluruh argumen yang diterimanya. Object itu mirip array, dapat diindeks dan punya length, tetapi bukan array sungguhan, sehingga metode array seperti map tidak ada padanya. Kode lama menanggulanginya dengan menyalin arguments ke array terlebih dahulu, dan langkah tambahan itulah yang dihilangkan rest parameter. Saat ini arguments hanya perlu dikenali sebagai peninggalan sejarah, yaitu ketika membaca kode lama yang masih memakainya.
function hitungLama(a, b) {
console.log(typeof arguments);
console.log(arguments.length);
try {
arguments.map(x => x * 2);
} catch (error) {
console.log("error:", error.message);
}
}
hitungLama(3, 4);object
2
error: arguments.map is not a functionKeluarannya menegaskan sifat arguments, terhitung sebagai object, panjangnya mengikuti argumen yang benar-benar diterima, tetapi map tidak tersedia padanya. Arrow function bahkan tidak membawa arguments sama sekali, sehingga rest parameter adalah satu-satunya cara yang masuk akal untuk mengumpulkan argumen di kode modern.
Ringkasan#
- Nilai default mengisi parameter yang argumennya tidak diberikan atau bernilai
undefined, dan tidak aktif bila argumennyanull. - Ekspresi default dievaluasi pada setiap pemanggilan, boleh berupa pemanggilan fungsi, dan dapat merujuk parameter yang berada di depannya.
- Pola
pembagi = wajib("pembagi")menjadikan parameter wajib, karena pemanggilan tanpa argumen langsung memunculkan error yang menyebut namanya. - Rest parameter
...sisamengumpulkan argumen sisanya menjadi array sungguhan, wajib berada di posisi terakhir, dan menggantikanargumentsdari kode lama.
Referensi#
- Default parameters — MDN Web Docs — aturan nilai default dan saat ekspresinya dievaluasi.
- Rest parameters — MDN Web Docs
— aturan rest parameter serta perbedaannya dengan
arguments. - Rest parameters and spread syntax — The Modern JavaScript Tutorial — penjelasan rest dan spread dalam satu bab dengan contoh.