Nested Object & Optional Chaining
Object bertingkat seperti respons API nyata, dan akses aman dengan optional chaining (?.). Ditambah pasangan wajibnya: nullish coalescing (??) untuk nilai default yang tidak mengorbankan 0 atau string kosong.
Object Bertingkat: Bentuk Data Dunia Nyata
Data dari API hampir tidak pernah datar. Ia bertingkat, karena dunia nyata bertingkat: user PUNYA alamat, alamat PUNYA kota, kota PUNYA kode pos.
const user = {
nama: "Budi",
alamat: {
kota: "Bandung",
kode: { pos: "40111" },
},
};
console.log(user.alamat.kota); // "Bandung"
console.log(user.alamat.kode.pos); // "40111"Rantai akses dibaca dari kiri ke kanan, tiap titik masuk satu level lebih dalam. Selama semua level ada, semuanya baik-baik saja.
Masalahnya: Satu Level Hilang, Semua Error
Masalah muncul karena data nyata tidak selalu lengkap. Tidak semua user mengisi alamat:
const user2 = { nama: "Ani" }; // tidak punya alamat!
console.log(user2.alamat.kota);
// TypeError: Cannot read properties of undefinedError ini terjadi berlapis: user2.alamat menghasilkan undefined, lalu undefined.kota melempar error dan SELURUH program berhenti. Sebelum era modern, programmer menulis tameng berlapis yang melelahkan:
// Cara lama: piramida pengecekan
const kota = user2.alamat && user2.alamat.kota ? user2.alamat.kota : "Tidak diketahui";Bisa dibayangkan betapa buruknya ini untuk rantai 4-5 level.
Solusi: Optional Chaining (?.)
console.log(user2.alamat?.kota); // undefined (TIDAK error!)Tanda ?. berarti: "kalau bagian kiri null atau undefined, berhenti di sini dan kembalikan undefined, jangan lanjutkan". Rantai panjang pun aman:
const kode = user2.alamat?.kode?.pos; // undefined, tanpa errorIa juga bekerja untuk pemanggilan method yang mungkin tidak ada, dan akses array:
user2.sapa?.(); // tidak error walau method sapa tidak ada
const pertama = daftar?.[0]; // aman untuk array yang mungkin nullContoh nyata, render daftar user yang datanya tidak seragam:
const users = [
{ nama: "A", alamat: { kota: "Bandung" } },
{ nama: "B" },
{ nama: "C", alamat: { kota: "Jakarta" } },
];
for (const u of users) {
console.log(u.nama + ": " + (u.alamat?.kota ?? "-"));
}
// A: Bandung, B: -, C: Jakarta (tanpa satu pun error)Pasangan Wajib: Nullish Coalescing (??)
?. sering menghasilkan undefined, dan kamu biasanya ingin menampilkan sesuatu yang lebih ramah. Di sinilah ?? masuk: "pakai nilai kanan kalau kiri null/undefined".
const kota = user2.alamat?.kota ?? "Tidak diketahui";
console.log(kota); // "Tidak diketahui"Kenapa tidak pakai || saja? Karena || menganggap SEMUA nilai falsy (0, "", false, NaN) sebagai "kosong":
const qty = 0;
console.log(qty || 10); // 10 (SALAH! qty memang 0, bukan kosong)
console.log(qty ?? 10); // 0 (BENAR, 0 dipertahankan)Ini jebakan klasik di form dan keranjang belanja: jumlah 0 atau harga 0 adalah data valid, bukan data hilang. ?? hanya bereaksi terhadap null/undefined, jadi data valid tidak tertimpa.
Jebakan Umum
?. tidak bisa dipakai di sisi kiri assignment. user.alamat?.kota = "X" adalah syntax error. Logis: kalau alamat tidak ada, mau disimpan ke mana?
Mencampur ?? dengan || atau && tanpa kurung dilarang sintaks: (a ?? b) || c wajib pakai kurung eksplisit. Ini disengaja agar programmer tidak salah paham prioritas operator.
Terlalu banyak ?. menutupi bug data. Kalau rantai a?.b?.c?.d selalu undefined, mungkin masalahnya bukan aksesnya, tapi datanya memang rusak dari sumber. Gunakan ?. untuk ketidakpastian yang WAJAR (field opsional), bukan untuk menambal data yang seharusnya selalu ada.
Catatan teknis:
?.melakukan short-circuit: begitu menemui null/undefined, sisa rantai TIDAK dievaluasi sama sekali (termasuk pemanggilan fungsi di dalamnya). Ini juga berarti efek samping di kanan?.tidak akan jalan, jadi jangan taruh operasi penting di sana.
export default function App(): JSX.Element { return <h1>Hello world</h1> }
Tantangan
Akses Aman Bertingkat
Diberi array users, beberapa tidak punya alamat. Tampilkan kota tiap user dengan ?. dan fallback "-" bila tidak ada. Jangan sampai error. Data tidak lengkap adalah kenyataan sehari-hari di aplikasi nyata: profil user yang field-nya opsional, respons API versi lama yang belum punya field baru, atau data impor CSV yang kolomnya bolong. Optional chaining membuat kodemu tahan terhadap semua itu tanpa piramida if.
<!doctype html> <html> <head> <meta charset="utf-8" /> </head> <body> <h1>Halo JS</h1> <p>Buka console preview untuk melihat output.</p> <script src="index.js"></script> </body> </html>