Optional chaining dan nullish coalescing

Akses properti dalam yang aman dengan ?. dan nilai cadangan dengan ??.

Daftar isi

Data dari sumber luar jarang lengkap, properti yang diharapkan bisa saja tidak ada atau bernilai null. Optional chaining ditulis ?., yaitu operator akses yang berhenti dengan aman dan menghasilkan undefined ketika jalurnya terputus. Nullish coalescing ditulis ??, yaitu operator yang menyediakan nilai cadangan untuk null dan undefined. Topik ini membahas keduanya, batasan pemakaiannya, serta kombinasi yang menjadi pola standar untuk membaca data bersarang.

Rantai akses yang berhenti dengan aman#

Rantai akses biasa berhenti dengan error TypeError begitu salah satu mata rantainya bernilai null atau undefined. Operator ?. mengubah perilaku itu, rantai berhenti pada mata rantai yang kosong dan seluruh ekspresi bernilai undefined tanpa melempar apa pun. Program tetap berjalan, dan keputusan apa yang harus dilakukan diserahkan ke kode yang membaca hasilnya.

js Contoh: rantai akses biasa versus rantai dengan ?.
// Rantai biasa berhenti dengan error, rantai ?. berhenti dengan undefined.
const konfigurasi = { tampilan: { tema: "gelap" } };

console.log(konfigurasi.tampilan.tema);

try {
  console.log(konfigurasi.audio.volume);
} catch (error) {
  console.log("error:", error.message);
}

console.log(konfigurasi.audio?.volume);
text Keluaran
gelap
error: Cannot read properties of undefined (reading 'volume')
undefined

Baris kedua membuktikan perilaku lama, akses volume pada konfigurasi.audio yang tidak ada melempar error dan hanya tertangkap karena dibungkus try/catch. Baris terakhir memakai ?. pada tempat yang sama dan menghasilkan undefined tanpa error. Perlu diingat bahwa ?. hanya melindungi akses yang ditulis dengannya, sehingga setiap mata rantai yang mungkin kosong membutuhkan tanda ?. sendiri-sendiri.

Diagram berikut memperlihatkan rantai yang sama pada data respons bersarang. Rantai berhenti ketika pengaturan bernilai null, dan ?? kemudian mengambil alih dengan nilai cadangannya.

respons.data?.penggunapengguna.pengaturannull.temaundefinedtema"terang"?? mengambil nilai cadangan bila rantai berhentiTanpa ?., akses properti pada null melempar error.
Optional chaining berhenti pada mata rantai null dan menghasilkan undefined, lalu nullish coalescing menggantinya dengan nilai cadangan

Optional chaining untuk metode#

Metode juga bisa dipanggil dengan pelindung yang sama. Bentuk ?.() memanggil fungsi hanya bila propertinya memang ada, sedangkan bentuk ?.[] mengakses kunci yang ditulis dalam kurung siku dengan pelindung serupa. Keduanya berguna saat fitur bersifat opsional, misalnya object yang boleh punya atau tidak punya metode pencatat.

js Contoh: pemanggilan metode dengan ?.
// ?.() memanggil metode hanya bila metodenya memang ada.
const kalkulator = { mulai() { return "dihitung"; } };

console.log(kalkulator.mulai?.());
console.log(kalkulator.hitung?.());
text Keluaran
dihitung
undefined

Metode mulai ada dan menghasilkan dihitung, sedangkan hitung tidak ada dan pemanggilannya berhenti dengan undefined tanpa error. Tanpa pelindung, kalkulator.hitung() akan melempar TypeError karena undefined bukan fungsi. Bentuk ?.[] bekerja dengan pola sama pada kunci dari variabel, misalnya daftar?.[indeks] yang berhenti bila daftarnya tidak ada. Perlu ditegaskan bahwa pelindung hanya menguji keberadaan bagian di depannya, pemanggilan ?.() menguji ada tidaknya metode, bukan keberhasilan eksekusinya. Metode yang ada tetapi melempar error tetap melempar error, dan itu memang perilaku yang diharapkan. Dengan tiga bentuk ini, pelindung ?. mencakup seluruh cara mengakses isi object dan array.

Kapan optional chaining menutupi bug#

?. bukan pengganti pemeriksaan data, melainkan alat untuk data yang memang boleh kosong. Properti yang seharusnya selalu ada tetapi ternyata undefined menandakan ada masalah, misalnya kunci salah tulis atau data yang gagal dibangun. Rantai ?. mengubah tanda bahaya itu menjadi undefined yang diam, dan bug berpindah jauh dari sumbernya ke baris yang membaca hasilnya. Penelusuran menjadi sulit, karena baris yang gagal dan baris yang salah tidak lagi berdekatan.

Aturan praktisnya sederhana. Gunakan ?. pada jalur yang ketiadaannya adalah keadaan wajar, misalnya pengaturan opsional dari respons server. Hindari ?. pada jalur yang semestinya pasti ada, dan tangani ketiadaannya secara eksplisit dengan pemeriksaan atau pesan yang jelas. Dengan pembagian ini, ?. menangani bagian yang memang belum pasti, sedangkan bagian yang wajib tetap memunculkan error ketika rusak.

Nullish coalescing sebagai nilai cadangan#

Hasil undefined dari rantai ?. biasanya perlu diganti nilai yang masuk akal, dan tugas itu milik nullish coalescing. Ekspresi a ?? b menghasilkan a selama a bukan null dan bukan undefined, dan hanya dua nilai itulah yang memicu cadangan b. Operator || terlihat serupa tetapi berbeda batasannya, ia mundur ke cadangan untuk semua nilai falsy, yaitu nilai yang dianggap salah, termasuk 0 dan string kosong.

js Contoh: batasan ?? dibandingkan dengan ||
// ?? hanya mundur pada null dan undefined, || mundur pada semua nilai falsy.
const suhu = 0;

console.log(suhu || 25);
console.log(suhu ?? 25);

const namaPanggilan = "";

console.log(namaPanggilan || "Tanpa nama");
console.log(namaPanggilan ?? "Tanpa nama");
text Keluaran
25
0
Tanpa nama

Suhu 0 lolos dari ?? dan tetap 0, sedangkan || menganggapnya kosong dan menggantinya dengan 25. Nama panggilan berupa string kosong juga masih lolos dari ??, sehingga baris terakhir keluaran berupa baris kosong, dan itulah string kosong yang dicetak apa adanya. Perbedaan ini penting ketika nol, string kosong, atau false adalah data yang sah, bukan tanda ketiadaan, karena || tidak mampu membedakannya dari nilai yang hilang. Karena ?? hanya peduli dua nilai itu, rantai ?. di depannya dapat dirangkai langsung, hasil undefined apa pun akan ditangkap cadangannya.

Menggabungkan ?. dan ??#

Kombinasi ?. dan ?? adalah pola standar untuk membaca data bersarang dari sumber luar. Rantai ?. menangani jalur yang mungkin terputus, sedangkan ?? memberi nilai cadangan ketika hasil akhirnya null atau undefined. Keduanya saling melengkapi tanpa satu pun pemeriksaan if.

js konfigurasi.js
// Kombinasi ?. dan ?? pada data bersarang yang bisa kosong.
const respons = {
  status: "ok",
  data: { pengguna: { nama: "Dewi", pengaturan: null } },
};

const tema = respons.data?.pengguna?.pengaturan?.tema ?? "terang";
const nama = respons.data?.pengguna?.nama ?? "tamu";

console.log(tema);
console.log(nama);
text Keluaran
terang
Dewi

Properti pengaturan bernilai null, sehingga akses tema berhenti dengan aman pada tanda ?. dan ?? mengisinya dengan terang. Baris kedua membuktikan jalur yang utuh tetap bekerja normal, nama terbaca tanpa perlu cadangan. Satu batasan sintaks perlu diingat, ?? tidak boleh dipadukan langsung dengan || atau && dalam satu ekspresi tanpa tanda kurung, dan pelanggarannya memicu error sintaks. Dengan tanda kurung, gabungannya sah dan urutan penilaiannya menjadi jelas. Pola ini mudah diperluas, tambahkan ?. di setiap mata rantai yang mungkin kosong, lalu satu ?? di ujung untuk nilai defaultnya. Data yang lebih dalam pun tetap ditangani dengan bentuk yang sama, tingkat keruwetannya hanya bertambah pada jumlah ?.-nya.

Ringkasan#

  • ?. menghentikan rantai akses dengan menghasilkan undefined ketika salah satu mata rantainya null atau undefined, baik untuk properti, metode ?.(), maupun kunci ?.[].
  • ?. hanya untuk jalur yang memang boleh kosong, karena pada jalur yang wajib ada, tanda ini menyembunyikan bug logika dari sumbernya.
  • ?? mengambil cadangan hanya untuk null dan undefined, sedangkan || mundur pada semua nilai falsy termasuk 0 dan string kosong.
  • Pola standar data bersarang memadukan keduanya, rantai ?. di setiap mata rantai yang mungkin kosong dan satu ?? di ujung untuk nilai cadangannya.

Referensi#