Belajar dengan membaca secara berurutan

Default Parameter dan Rest Parameter — Value Bawaan dan Cara Menampung Sisa Argument

Membahas default parameter, rest parameter yang mengumpulkan argument ke dalam array, dan pola options object.

Ada argument yang value-nya hampir selalu sama di setiap pemanggilan, seperti ongkos kirim atau tarif pajak. Kalau argument itu tidak diisi, tidak ada error yang muncul; kamu baru sadar ada yang terlewat saat undefined ikut tampil di output.

Artikel ini membahas default parameter, yang menentukan value untuk argument yang tidak diisi, rest parameter, yang menampung argument dalam jumlah berapa pun, dan pola options, yang mengoper pengaturan sebagai satu object.

Membuat Argument Boleh Dikosongkan — Default Parameter

Misalnya ada function yang menyusun data pemesanan ruang rapat, dengan durasi yang hampir selalu 1 jam dan tata letak yang hampir selalu model classroom. Kalau kamu tetap harus menulis ketiga argument di setiap pemanggilan, satu value yang sebenarnya ingin kamu ubah jadi tenggelam di antara yang lain.

Default parameter (cara menentukan lebih dulu value yang dipakai kalau argument tidak dioper) ditulis dengan menambahkan = di daftar parameter, seperti hours = 1. Argument untuk parameter yang punya value bawaan boleh dikosongkan oleh pemanggil.

// Value bawaan ditulis dengan menambahkan "= value" di daftar parameter
const reserveRoom = (roomName, hours = 1, layout = "classroom") => {
  return `${roomName} / ${hours} jam / ${layout}`;
};

// Kalau argument ke-3 tidak diisi, value bawaan "classroom" yang dipakai
console.log(reserveRoom("Ruang A", 2));               // Ruang A / 2 jam / classroom

// Kalau value-nya dioper, value bawaan tidak dipakai
console.log(reserveRoom("Ruang A", 2, "boardroom"));  // Ruang A / 2 jam / boardroom

// Kalau argument ke-2 juga tidak diisi, kedua value bawaan dipakai
console.log(reserveRoom("Ruang A"));                  // Ruang A / 1 jam / classroom
Argument Diisi Mulai dari Kiri
Oper Ruang Ake roomNameTidak adavalue bawaanroomName =Ruang AOper 2ke hoursValue bawaan 1tidak dipakaihours = 2layouttidak diisiValue bawaandipakai di sinilayout =classroom
Diagram ini menguraikan reserveRoom("Ruang A", 2) per posisi parameter. Walaupun ada value bawaan, value itu tidak dipakai kalau argument-nya dioper.

Argument hanya bisa dikosongkan mulai dari sebelah kanan, jadi letakkan parameter yang punya value bawaan di bagian akhir. Kalaupun kamu hanya ingin mengubah argument ke-3, posisi ke-2 tetap harus diisi value.

Hitung perkiraan ongkos kirim. boxCount dan tarif per kardus untuk tiap wilayah sudah dideklarasikan, dan ongkos kirimnya adalah tarif per kardus × jumlah kardus.

① Tulis function yang menerima jumlah kardus dan wilayah lalu mengembalikan ongkos kirim, dengan value bawaan 1 kardus dan Honshu (pulau utama Jepang).

② Kosongkan wilayahnya dan tampilkan ongkos kirim untuk boxCount kardus sebagai "Honshu: X yen".

③ Isi wilayah dengan Hokkaido dan tampilkan "Hokkaido: X yen".

④ Panggil tanpa argument sama sekali dan tampilkan "Bawaan: X yen".

(Kalau berjalan dengan benar, penjelasan akan muncul.)

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Isi Argument yang Tidak Dioper — undefined dan Value Bawaan

Kalau argument untuk parameter tanpa value bawaan tidak diisi, perhitungan atau string yang memakainya tetap berjalan. Karena eksekusinya tidak berhenti, belakangan kamu harus mencari sendiri pemanggilan mana yang lupa mengopernya.

Parameter yang tidak menerima argument berisi undefined. Value bawaan hanya dipakai kalau argument-nya undefined — kalau kamu mengoper null, 0, atau string kosong, value yang kamu oper itulah yang dipakai.

const notifyStatus = (orderId, status = "Diterima") => `${orderId}: ${status}`;

// Dikosongkan maupun dioper undefined, keduanya memakai value bawaan
console.log(notifyStatus("A-1021"));             // A-1021: Diterima
console.log(notifyStatus("A-1021", undefined));  // A-1021: Diterima

// null dianggap value yang dioper, jadi value bawaan tidak dipakai
console.log(notifyStatus("A-1021", null));       // A-1021: null

// Parameter tanpa value bawaan yang tidak diisi berisi undefined
const plainStatus = (orderId, status) => `${orderId}: ${status}`;
console.log(plainStatus("A-1021"));              // A-1021: undefined
Dikosongkan vs. Dioper null
Dipanggiltanpa statusstatus =undefined= "Diterima"dipakaiA-1021:DiterimaOper nullke statusstatus =nullValue bawaantidak dipakaiA-1021:null
status yang dikosongkan berisi undefined, jadi ekspresi value bawaan dijalankan. null diperlakukan sebagai value yang dioper, jadi ekspresi value bawaan tidak dijalankan.

Tabel di bawah menunjukkan isi status dan apa yang ditampilkan untuk tiap argument kedua yang dioper ke notifyStatus. Mengoper undefined memberi hasil yang sama dengan mengosongkan argument, sedangkan null, sama seperti string, ditampilkan apa adanya.

PemanggilanIsi statusYang ditampilkan
notifyStatus("A-1021")Value bawaan, DiterimaA-1021: Diterima
notifyStatus("A-1021", "Dikirim")DikirimA-1021: Dikirim
notifyStatus("A-1021", undefined)Value bawaan, DiterimaA-1021: Diterima
notifyStatus("A-1021", null)nullA-1021: null

Kalau null yang Dioper, Value Bawaan Tidak Dipakai

null adalah value yang berarti "sengaja dikosongkan", jadi value bawaan di daftar parameter tidak menggantikannya. Kalau kamu tetap ingin memakai value cadangan saat respons API berisi null, jangan pasang value bawaan di parameter, tapi pakai ?? di dalam function, seperti const shown = status ?? "Diterima";.

Tampilkan jumlah stok. products sudah dideklarasikan; isinya mencakup satu barang dengan stok 0, satu tanpa key stock, dan satu yang stoknya null.

① Tulis stockLabel yang menerima jumlah stok dan mengembalikan "stok: X", dengan "dicek" sebagai value bawaan.

② Tampilkan semua barang dalam bentuk "[nama barang] stok: X".

③ Tulis stockLabelSafe yang juga mengubah null menjadi "dicek", tanpa memakai value bawaan.

④ Tampilkan lagi Kabel dan USB Hub, kali ini dengan stockLabelSafe.

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Menampung Argument dalam Jumlah Berapa Pun — Rest Parameter

Ada function yang menerima jumlah value berbeda di setiap pemanggilan, seperti tag pada sebuah produk atau rincian di laporan pengeluaran. Walaupun kamu menyiapkan lima parameter, suatu saat akan ada pemanggilan yang butuh yang keenam, dan parameter yang tidak terpakai selalu berisi undefined.

Rest parameter (cara menerima sisa argument yang dikumpulkan ke dalam satu array; disebut juga variadic argument) ditulis sebagai ...labels di akhir daftar parameter. Simbol ... ini sama dengan yang dipakai untuk mengumpulkan sisa element saat destructuring, bedanya di sini yang dikumpulkan adalah argument. Rest parameter hanya boleh menjadi parameter terakhir; menaruh parameter lain setelahnya akan menghasilkan SyntaxError.

// Dengan menulis ...labels, argument yang diterima dikumpulkan ke dalam satu array
const buildTags = (...labels) => `Tag (${labels.length}): ${labels.join(" / ")}`;

console.log(buildTags("Gratis Ongkir", "Stok Ada"));  // Tag (2): Gratis Ongkir / Stok Ada
console.log(buildTags("Baru"));                        // Tag (1): Baru

// Sebaliknya, ... di dalam tanda kurung pemanggilan mengubah array kembali menjadi argument
console.log(buildTags(...["Baru", "Terbatas"]));       // Tag (2): Baru / Terbatas

// Kalau ada juga parameter yang diberi nama, taruh rest parameter di akhir
const buildNotice = (orderId, ...notes) => `${orderId} (${notes.join(", ")})`;

console.log(buildNotice("A-1021", "Berpendingin", "Jam antar"));  // A-1021 (Berpendingin, Jam antar)
console.log(buildNotice("A-1022"));                              // A-1022 ()
Ke Parameter Mana Tiap Value Masuk
Pertama"A-1021"Masuk keorderIdKedua"Berpendingin"Masuk kenotes[0]Ketiga"Jam antar"Masuk kenotes[1]
Value pertama masuk ke orderId, dan sisanya masuk berurutan ke element notes. Rest parameter menerima semua yang tersisa setelah parameter yang diberi nama.

Rest parameter tidak bisa diberi value bawaan, tapi kalau tidak ada argument yang dioper untuknya, notes berisi array kosong, bukan undefined. Sebaliknya, kalau kamu punya array dan ingin mengoper isinya sebagai argument satu per satu, tulis ... di dalam tanda kurung pemanggilan.

Jumlahkan biaya transportasi dari sebuah perjalanan dinas. trainFare, busFare, dan taxiFare sudah dideklarasikan.

① Tulis sumExpenses dengan rest parameter supaya menjumlahkan semua nominal yang diterima lalu mengembalikan totalnya.

② Tampilkan total ketiga biaya sebagai "Total: X yen".

③ Tampilkan hasil pemanggilan tanpa argument dengan bentuk yang sama.

④ Tulis summarize yang menerima nama kategori diikuti nominal dalam jumlah berapa pun, lalu oper "Transportasi" beserta ketiga biaya dan tampilkan "Transportasi: X yen (N item)".

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Mengoper Pengaturan dengan Nama — Options Object dan Destructuring

Kalau pengaturannya makin banyak, seperti saat mengirim email, pemanggilannya lama-lama jadi seperti sendMail(to, subject, false, true). Arti false dan true itu tidak bisa diketahui tanpa membuka definisi function-nya.

Dengan pola options (cara mengoper beberapa pengaturan yang dikumpulkan dalam satu object), sisi penerima melakukan destructuring pada object itu dan memberi value bawaan untuk tiap key. Untuk menangani pemanggilan yang tidak mengoper pengaturan sama sekali, tambahkan = {} setelah pola destructuring supaya object kosong yang dipakai kalau tidak ada object yang dioper.

// Makin banyak parameter, makin sulit mengetahui apa yang dioper sebuah pemanggilan
const sendMailOld = (to, subject, isUrgent, withPdf) =>
  `${to} / ${subject} / ${isUrgent} / ${withPdf}`;

console.log(sendMailOld("budi@example.com", "Info pengiriman", false, true));
// budi@example.com / Info pengiriman / false / true

// Pola options: kumpulkan pengaturan dalam satu object, lalu lakukan destructuring di sisi penerima
const sendMail = (to, { subject = "Pemberitahuan", isUrgent = false } = {}) =>
  `${to} / ${subject} / ${isUrgent}`;

console.log(sendMail("budi@example.com", { isUrgent: true }));  // budi@example.com / Pemberitahuan / true
console.log(sendMail("budi@example.com"));                     // budi@example.com / Pemberitahuan / false
Hanya Key yang Ditulis yang Ditimpa
Oper{ isUrgent: true }true sampaike isUrgentisUrgent =trueTidak ada subjectdi pemanggilan iniValue bawaansubject dipakaisubject =PemberitahuanTanpa objectpengaturan= {} mengisiobject kosongKeduanyavalue bawaan
Hanya key yang kamu tulis yang dioper; key yang tidak ditulis tetap memakai value bawaannya. = {} di bagian akhir menangani pemanggilan yang tidak mengoper object sama sekali.

Alih-alih bergantung pada urutan parameter, setiap value diberi label lewat key-nya, jadi pemanggilan tetap mudah dibaca walaupun pengaturannya bertambah. Key dicocokkan berdasarkan nama, jadi walaupun urutan penulisannya berbeda, seperti { isUrgent: true, subject: "Kirim ulang" }, value yang diterima tetap sama.

Tanpa = {}, Hasilnya TypeError

Kalau kamu hanya menulis pola destructuring, seperti { subject = "Pemberitahuan" }, pemanggilan yang tidak mengisi argument kedua akan melempar TypeError: Cannot read properties of undefined (reading 'subject'). Penyebabnya, JavaScript mencoba membaca key dari undefined, yaitu isi parameter yang tidak diisi itu.

Ubah cara harga sebuah bento ditampilkan dengan memakai object pengaturan. lunchPrice sudah dideklarasikan.

① Tulis formatPrice yang menerima harga sebelum pajak dan object pengaturan, lalu mengembalikan string seperti "1058 yen". Terima pengaturannya dengan destructuring, dengan value bawaan tarif pajak 0.08 dan satuan "yen".

② Tampilkan hasil pemanggilan tanpa pengaturan.

③ Tampilkan hasil dengan tarif pajak 0.1 dan satuan "yen (makan di tempat)".

④ Tampilkan hasil dengan tarif pajak 0.

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output
QUIZ

Cek Pemahaman

Jawab setiap pertanyaan satu per satu.

Soal 1Dengan const addFee = (price, fee = 500) => price + fee;, apa yang dikembalikan addFee(1000, undefined)?

Soal 2Apa yang dikembalikan const countNotes = (id, ...notes) => notes.length; saat dipanggil sebagai countNotes("A-1021")?

Soal 3Apa yang dikembalikan const send = (to, { urgent = false } = {}) => urgent; saat dipanggil sebagai send("budi@example.com")?