Masukkan Password
87 Rantai Opsional
Kita bahas Optional Chaining (?.) dari dasar sampai benar-benar paham, terutama bagian yang sering membingungkan: kenapa error bisa terjadi, bagaimana ?. menghentikan error, dan bagaimana membaca product?.features?.ram langkah demi langkah.
1. Apa itu Optional Chaining?
Optional chaining adalah fitur JavaScript yang diperkenalkan di ES2020.
Syntax-nya:
?.
Tujuannya sederhana:
Mencoba mengakses property yang mungkin tidak ada, tanpa membuat program error ketika nilai di tengah ternyata
nullatauundefined.
Contoh:
const user = {
name: "John"
};
console.log(user.address.city);
Ini akan menghasilkan error.
Kenapa?
Karena:
user.address
tidak ada, sehingga hasilnya:
undefined
Lalu JavaScript mencoba melakukan:
undefined.city
Nah, ini tidak boleh.
2. Kenapa undefined.property menghasilkan error?
Ini konsep yang sangat penting.
Misalnya:
const user = {
name: "John"
};
console.log(user.address);
Hasil:
undefined
Sampai sini tidak ada masalah.
Karena property address memang tidak ada, JavaScript hanya mengembalikan undefined.
Tetapi kalau:
console.log(user.address.city);
JavaScript harus melakukan:
user.address
↓
undefined
↓
undefined.city
↓
ERROR ❌
undefined tidak memiliki property city.
Hal yang sama berlaku untuk null:
const user = {
contact: null
};
console.log(user.contact.email);
Alurnya:
user.contact
↓
null
↓
null.email
↓
ERROR ❌
Jadi masalah utamanya bukan sekadar property tidak ada.
Masalahnya adalah:
Kita mencoba mengambil property berikutnya dari nilai
undefinedataunull.
3. Masalah seperti ini sering terjadi pada nested object
Misalnya kita punya:
const user = {
name: "John",
address: {
city: "Jakarta",
country: "Indonesia"
}
};
Kita bisa mengambil:
console.log(user.name);
Hasil:
John
Dan:
console.log(user.address.city);
Hasil:
Jakarta
Karena strukturnya memang ada:
user
└── address
├── city
└── country
Tetapi bayangkan ada user lain:
const user = {
name: "Mark",
address: null
};
Kalau kita melakukan:
console.log(user.address.city);
maka:
user.address
↓
null
↓
null.city
↓
ERROR ❌
Nah, optional chaining dibuat untuk situasi seperti ini.
4. Cara menggunakan Optional Chaining
Kita tinggal mengganti:
.
menjadi:
?.
Contoh:
console.log(user.address?.city);
Sekarang JavaScript akan mengecek:
“Apakah
user.addressadalahnullatauundefined?”
Kalau iya:
undefined
langsung dikembalikan.
Tidak diteruskan ke .city.
5. Perhatikan perbedaannya
Tanpa optional chaining:
user.address.city
Kalau address adalah null:
user.address
↓
null
↓
null.city
↓
ERROR ❌
Dengan optional chaining:
user.address?.city
Kalau address adalah null:
user.address
↓
null
↓
?.city
↓
undefined
Jadi ?. seperti mengatakan:
“Kalau bagian sebelumnya ada, lanjut. Kalau
null/undefined, berhenti dan hasilnyaundefined.”
6. Analogi sederhana
Bayangkan kita sedang mencari rumah.
Kita punya alamat:
Kota
└── Jalan
└── Rumah
└── Kamar
Normal:
Kota → Jalan → Rumah → Kamar
Tetapi ternyata Rumah-nya tidak ada.
Kalau kita tetap berkata:
“Masuk ke rumah, lalu cari kamar.”
Ya tidak bisa. 😄
Optional chaining seperti mengatakan:
“Kalau rumahnya ada, masuk dan cari kamar. Kalau rumahnya tidak ada, berhenti saja.”
Dalam JavaScript:
city.street?.house?.room
Kalau house null, JavaScript tidak akan mencoba:
null.room
7. Contoh dari lecture: Products
Sekarang kita masuk ke contoh yang digunakan di lecture.
Misalnya:
const products = [
{
id: 1,
name: "Laptop",
features: {
ram: "16GB"
},
model: {
year: 2024
}
},
{
id: 2,
name: "T-Shirt",
model: null,
details: {
size: "L"
}
}
];
Perhatikan bahwa struktur kedua product berbeda.
Product pertama
Laptop
├── name
├── features
│ └── ram
└── model
└── year
Product kedua
T-Shirt
├── name
├── model → null
└── details
└── size
Product kedua tidak punya features.
8. Masalah tanpa Optional Chaining
Kita melakukan:
products.forEach((product) => {
console.log(product.features.ram);
});
Untuk product pertama:
product
↓
features
↓
ram
↓
16GB
Aman.
Tetapi product kedua:
product
↓
features
↓
undefined
↓
undefined.ram
↓
ERROR ❌
Karena product kedua tidak memiliki features.
9. Gunakan ?.
Kita ubah menjadi:
console.log(product.features?.ram);
Sekarang alurnya:
Product pertama
product.features
↓
{ ram: "16GB" }
↓
?.ram
↓
"16GB"
Product kedua
product.features
↓
undefined
↓
?.ram
↓
undefined
Tidak ada error.
Inilah fungsi utama optional chaining.
10. ?. bukan berarti property harus ada
Ini juga penting.
Misalnya:
const user = {
name: "John"
};
Kita lakukan:
console.log(user.gender?.name);
Karena:
user.gender
adalah:
undefined
maka:
user.gender?.name
menghasilkan:
undefined
bukan error.
11. Bisa digunakan berkali-kali
Optional chaining bisa digunakan pada beberapa level.
Misalnya:
product?.features?.ram
Ada dua ?..
Mari kita baca dari kiri ke kanan.
product
↓
?.
↓
features
↓
?.
↓
ram
JavaScript melakukan pengecekan di setiap titik optional chaining.
12. Contoh product?.features?.ram
Misalnya:
const product = {
features: {
ram: "16GB"
}
};
Maka:
product?.features?.ram
hasilnya:
16GB
Karena semuanya tersedia.
Tetapi kalau:
const product = {
features: null
};
maka:
product?.features?.ram
berhenti di:
product
↓
features
↓
null
↓
?.ram
↓
undefined
Tidak mencoba:
null.ram
13. Bagaimana kalau object awalnya null?
Ini juga salah satu contoh penting dari lecture.
Misalnya array kita:
const products = [
{
name: "Laptop"
},
{
name: "T-Shirt"
},
null
];
Kemudian:
products.forEach((product) => {
console.log(product.name);
});
Untuk dua product pertama aman.
Tapi product ketiga:
product
↓
null
↓
null.name
↓
ERROR ❌
Kita bisa menggunakan:
product?.name
Sekarang:
product
↓
null
↓
?.name
↓
undefined
Tidak error.
14. Bisa digabung dengan nested property
Misalnya:
product?.features?.ram
Artinya:
“Kalau
productada, coba ambilfeatures. Kalaufeaturesada, coba ambilram. Kalau salah satu bagian yang dicek dengan?.adalahnullatauundefined, berhenti dan hasilkanundefined.”
Ini sangat berguna ketika data dari server/API tidak selalu memiliki struktur yang sama.
15. Bandingkan dengan if
Sebelum ada optional chaining, kita bisa melakukan pengecekan manual.
Misalnya:
if (product.features !== undefined) {
console.log(product.features.ram);
}
Atau:
if (product && product.features) {
console.log(product.features.ram);
}
Dengan optional chaining:
console.log(product?.features?.ram);
Jauh lebih pendek.
16. Optional chaining sebenarnya adalah “safe access”
Mental model yang bagus:
normal .
↓
"Aku yakin object ini ada."
optional ?.
↓
"Aku tidak yakin object ini ada.
Kalau ada, lanjut.
Kalau null/undefined, berhenti."
Contoh:
user.address.city
= Saya yakin address ada.
Sedangkan:
user.address?.city
= Saya tidak yakin address ada. Kalau ada, ambil city. Kalau tidak, jangan error.
17. undefined sebagai hasil bukan error
Ini penting supaya tidak salah memahami.
Misalnya:
const user = {};
console.log(user.address?.city);
Hasil:
undefined
Itu bukan error.
JavaScript mengatakan:
“Address tidak ada, jadi saya tidak bisa mengambil city. Saya kembalikan
undefined.”
Program tetap berjalan.
18. Optional chaining tidak mengubah object
Misalnya:
const user = {
name: "John"
};
const city = user.address?.city;
Optional chaining tidak membuat address, tidak mengubah object, dan tidak mengisi default.
Object tetap:
{
name: "John"
}
Hasil city hanya:
undefined
19. Bedakan ?. dengan .
| Syntax | Arti |
|---|---|
user.name | akses property biasa |
user.address.city | akses nested property biasa |
user.address?.city | akses city jika address tersedia |
user?.address?.city | akses aman dari level user sampai city |
Contoh:
user.address.city
Kalau address = null:
ERROR ❌
Sedangkan:
user.address?.city
kalau address = null:
undefined ✅
20. Hubungannya dengan null dan undefined
Kita sudah belajar sebelumnya:
undefined
Biasanya berarti:
“Nilainya belum ada / property tersebut tidak ditemukan.”
Contoh:
const user = {};
console.log(user.age);
hasil:
undefined
null
Biasanya berarti:
“Memang sengaja tidak ada nilai.”
Contoh:
const user = {
contact: null
};
Artinya:
User memang belum memiliki data contact.
Optional chaining menangani keduanya:
user.contact?.email
Kalau:
contact === undefined
→ undefined
Kalau:
contact === null
→ undefined
21. Optional chaining dan || berbeda
Ini juga penting karena sebelumnya kamu belajar ||.
Misalnya:
const user = {};
const name = user.name || "Unknown";
|| digunakan untuk memberikan fallback/default value.
Hasil:
Unknown
Sedangkan:
const name = user.name?.firstName;
?. digunakan untuk safe access.
Jadi:
?. → mencegah error saat akses property
|| → memberikan nilai cadangan
Keduanya bahkan bisa digabung:
const city = user.address?.city || "Unknown";
Artinya:
“Coba ambil city. Kalau tidak tersedia atau falsy, gunakan
Unknown.”
22. Contoh yang sangat realistis: API
Bayangkan kita mendapatkan data user dari server:
const user = {
name: "John",
profile: {
address: {
city: "Jakarta"
}
}
};
Kita bisa:
console.log(user.profile.address.city);
Tetapi user lain mungkin:
const user = {
name: "Mark",
profile: null
};
Kalau:
console.log(user.profile.address.city);
💥 Error.
Dengan:
console.log(user.profile?.address?.city);
hasilnya:
undefined
Dan aplikasi tidak crash hanya karena data tertentu tidak lengkap.
23. Optional chaining pada array
?. juga bisa digunakan ketika mengakses index array.
Misalnya:
const users = [
"John",
"Mark"
];
Kita bisa:
console.log(users?.[0]);
hasil:
John
Bentuk ini berguna ketika array-nya sendiri mungkin null/undefined.
Misalnya:
let users = null;
console.log(users?.[0]);
hasil:
undefined
tanpa error.
Perhatikan bentuknya:
users?.[0]
bukan:
users?[0] // ❌
24. Optional chaining pada function
Ada bentuk lain:
someFunction?.();
Artinya:
Kalau function tersebut ada, panggil. Kalau
null/undefined, jangan error.
Contoh:
let callback;
callback?.();
Tidak menghasilkan:
callback is not a function
karena optional call mengatakan:
Kalau
callbacktersedia, jalankan.
25. Tapi ?. bukan solusi untuk semua error
Ini penting.
Optional chaining hanya membantu ketika bagian yang dicek adalah:
null
atau
undefined
Misalnya:
const user = {
age: 28
};
console.log(user.age?.name);
Ini memang tidak error karena age adalah primitive number dan optional chaining menangani kasus tertentu.
Tetapi jangan berpikir:
“Kalau pakai
?., semua error JavaScript hilang.”
Tidak.
Misalnya:
user.calculateAge?.();
Kalau calculateAge ternyata adalah String:
{
calculateAge: "hello"
}
itu bukan null/undefined, sehingga bukan berarti aman dari semua jenis masalah pemanggilan.
26. Kesalahan yang sering dilakukan pemula
❌ Salah memahami ?. sebagai “property pasti ada”
Justru sebaliknya.
user.address?.city
berarti:
“Saya tidak yakin
addressada.”
❌ Mengira ?. membuat property otomatis ada
user.address?.city
tidak membuat:
user.address = {}
Tidak.
❌ Mengira hasilnya selalu null
Tidak.
Optional chaining menghasilkan:
undefined
ketika akses dihentikan karena null/undefined.
Contoh:
const user = {
address: null
};
console.log(user.address?.city);
hasil:
undefined
bukan:
null
27. Cara membaca expression panjang
Misalnya kamu menemukan kode:
product?.details?.specification?.ram
Jangan panik melihat banyak ?..
Baca dari kiri ke kanan:
product
↓
apakah product null/undefined?
↓ tidak
details
↓
apakah details null/undefined?
↓ tidak
specification
↓
apakah specification null/undefined?
↓ tidak
ram
Kalau berhenti di salah satu titik:
undefined
28. Hubungan dengan destructuring yang baru kita pelajari
Ini menarik karena kamu baru saja belajar object destructuring.
Misalnya:
const employee = {
name: "John",
age: 28
};
const { name, age } = employee;
Itu digunakan untuk:
mengambil property menjadi variable.
Sedangkan optional chaining:
employee.department?.name
digunakan untuk:
mengakses property yang mungkin tidak tersedia dengan aman.
Jadi keduanya punya tujuan berbeda.
Destructuring
↓
"Ambil data dari object"
Optional chaining
↓
"Ambil data dengan aman kalau mungkin tidak ada"
29. Hubungan dengan spread operator dan rest
Sekarang kamu sudah mempelajari beberapa syntax modern:
Destructuring
const { name, age } = employee;
Mengambil/membongkar data.
Spread
const newEmployee = {
...employee
};
Menyebarkan/meng-copy property.
Rest
const { name, ...others } = employee;
Mengumpulkan sisa property.
Optional chaining
employee.address?.city
Mengakses property secara aman.
Mental model:
Destructuring → BONGKAR
Spread → SEBAR
Rest → KUMPULKAN SISA
Optional ?. → AKSES DENGAN AMAN
30. Contoh lengkap
Misalnya:
const employees = [
{
name: "John",
workDetails: {
company: "ABC",
experience: 5
}
},
{
name: "Mark",
workDetails: null
},
null
];
Kita ingin mendapatkan:
- nama
- perusahaan
- pengalaman
Tanpa optional chaining:
employees.forEach((employee) => {
console.log(employee.name);
console.log(employee.workDetails.company);
console.log(employee.workDetails.experience);
});
Program akan error ketika bertemu:
workDetails: null
Dan juga ketika:
employee === null
Dengan optional chaining:
employees.forEach((employee) => {
console.log(employee?.name);
console.log(employee?.workDetails?.company);
console.log(employee?.workDetails?.experience);
});
Sekarang:
John
John
ABC
5
Mark
Mark
undefined
undefined
null
undefined
undefined
undefined
Program tetap berjalan.
31. Visualisasi paling penting
Ingat pola ini:
object?.property
Secara mental:
object
↓
null / undefined?
↙ ↘
YES NO
↓ ↓
return undefined property
Untuk nested:
object?.a?.b?.c
Visual:
object
│
├── null/undefined? → STOP → undefined
│
↓
a
│
├── null/undefined? → STOP → undefined
│
↓
b
│
├── null/undefined? → STOP → undefined
│
↓
c
Ini adalah inti seluruh lecture.
32. Ringkasan . vs ?.
| Kode | Jika property sebelumnya null/undefined |
|---|---|
user.address.city | ❌ Error |
user.address?.city | ✅ undefined |
user?.address.city | ⚠️ hanya user yang aman |
user?.address?.city | ✅ setiap level aman |
Perhatikan contoh terakhir:
user?.address?.city
Ini yang paling aman jika user maupun address sama-sama bisa tidak ada.
33. Cheat Sheet
OPTIONAL CHAINING
────────────────────────────────
Syntax:
object?.property
Tujuan:
akses property tanpa error
jika bagian sebelumnya null/undefined.
Contoh:
user?.name
Nested:
user?.address?.city
Array:
users?.[0]
Function:
callback?.()
Hasil ketika berhenti:
undefined
Mental model
.
→ "lanjut, saya yakin ada"
?.
→ "kalau ada lanjut,
kalau null/undefined berhenti"
34. Hubungkan dengan method yang sudah kamu pelajari
Sekarang coba lihat beberapa operasi yang sudah kamu pelajari:
movie.genre.includes("action");
Ada asumsi:
movie.genre pasti Array
Kalau ternyata:
movie.genre = undefined;
maka:
movie.genre.includes("action");
akan error.
Dalam situasi tertentu kita bisa menggunakan:
movie.genre?.includes("action");
Kalau genre tidak ada:
undefined
daripada error.
Namun, perlu diingat: hasilnya bisa menjadi undefined, bukan true/false. Jadi penggunaannya harus disesuaikan dengan kebutuhan.
35. Inti lecture dalam satu kalimat
Kalau harus mengingat satu kalimat saja, ingat ini:
Optional chaining (
?.) memungkinkan kita mengakses property berikutnya hanya jika nilai sebelumnya bukannullatauundefined; kalau ternyatanull/undefined, JavaScript berhenti dan mengembalikanundefinedtanpa error.
Dan pola paling penting:
product?.features?.ram
dibaca:
“Kalau
productada, ambilfeatures; kalaufeaturesjuga ada, ambilram; kalau salah satunyanullatauundefined, berhenti dan hasilnyaundefined.”
Peta konsep sampai lecture ini
MODERN JAVASCRIPT SYNTAX
│
├── Destructuring
│ ├── Array → berdasarkan posisi
│ └── Object → berdasarkan property name
│
├── Spread (...)
│ └── menyebarkan isi
│
├── Rest (...)
│ └── mengumpulkan sisa
│
└── Optional Chaining (?.)
└── mengakses property dengan aman
jika mungkin null/undefined
Jadi sekarang jangan sampai tertukar:
[ a, b ] = array
↓
ARRAY DESTRUCTURING
{ name, age } = object
↓
OBJECT DESTRUCTURING
[...array]
↓
SPREAD
{...object}
↓
SPREAD
[a, ...others] = array
↓
REST
{name, ...others} = object
↓
REST
object?.property
↓
OPTIONAL CHAINING