Dua chapter terakhir memperlakukan galat seperti satu teks pesan yang lewat di layar. Padahal setiap Error yang dilempar engine adalah object yang berisi informasi terstruktur: jenis galatnya, penjelasannya, dan jejak lokasi kejadian. Ketika galat tertangkap di catch, object itu utuh di tangan kita — dan penanganan yang tepat dimulai dari membaca isinya dengan benar.
Chapter ini membedah anatomi Error, memperkenalkan empat turunannya yang paling sering ditemui, lalu menutup dengan fitur cause untuk merekam akar masalah.
Anatomi: name, message, dan stack #
Membuat Error sama mudahnya dengan membuat object biasa: new Error("pesan"). Instance yang dihasilkan punya tiga properti utama:
const galat = new Error("Data pesanan tidak ditemukan");
console.log(galat.name);
console.log(galat.message);
console.log(typeof galat.stack);Output yang Dihasilkan:
Error
Data pesanan tidak ditemukan
stringKetiganya punya peran masing-masing:
name— jenis galat:"Error"untuk instance dasar. Nilai inilah yang muncul di depan transkrip, dan inilah yang biasa diperiksa untuk membedakan jenis kegagalan.message— penjelasan yang ditulis saat pembuatan:"Data pesanan tidak ditemukan". Pesan yang baik menyebut apa yang salah dan nilai apa yang terlibat.stack— sebuah string berisi daftar pemanggil, dari lokasi kegagalan sampai titik masuk program. Membacanya mendalam dibahas di chapter terakhir section ini; untuk saat ini cukup diketahui bahwa properti itu ada dan bertipe string, serta terisi otomatis tanpa perintah apa pun dari kita.
Sampai jumpa cause di bagian akhir, tiga properti inilah seluruh isi standar sebuah Error.
Dua cara menampilkannya juga perlu dikenali. Menggabungkan name dan message sebagai satu string adalah bentuk yang sama dengan transkrip Node — dan itu bukan kebetulan, karena String(galat) memang merakit keduanya:
const galat = new Error("Data pesanan tidak ditemukan");
console.log(String(galat));Output yang Dihasilkan:
Error: Data pesanan tidak ditemukanSementara itu, console.log(galat) pada object galat mencetak string stack lengkap — bukan isi object seperti pada object biasa. Karena itu di dalam catch kita biasanya mencetak error.message untuk ringkasan, dan mencetak object galatnya utuh hanya saat jejak at ... memang dibutuhkan.
Terakhir, ingat bahwa Error tetap sebuah object: properti tambahan boleh dilekatkan sesuai kebutuhan pelaporan:
const galat = new Error("Data pesanan tidak ditemukan");
galat.kode = "PES-404";
galat.idPesanan = 1038;
console.log(galat.kode);
console.log(galat.idPesanan);Output yang Dihasilkan:
PES-404
1038Polanya dipakai untuk melabeli galat dengan konteks aplikasi — kode kesalahan, id data yang terlibat — tanpa mengubah name maupun message-nya.
Satu keunikan constructor terakhir: Error juga berfungsi tanpa new. Pemanggilan biasa tetap menghasilkan instance yang utuh — perilaku yang tidak dimiliki kebanyakan constructor lain:
const tanpaNew = Error("pesan tanpa new");
console.log(tanpaNew instanceof Error);
console.log(tanpaNew.message);Output yang Dihasilkan:
true
pesan tanpa newMeski sah, tuliskan new Error(...) secara konsisten — bentuk itu menyatakan niat membuat instance secara eksplisit dan tetap menjadi gaya yang paling umum ditemui.
Empat Turunan Error yang Paling Sering Ditemui #
Error hanyalah akar. Engine melempar turunan-turunannya sesuai jenis masalah, dan masing-masing membawa name sendiri:
| Jenis | Kapan muncul | Contoh situasi |
|---|---|---|
TypeError | Operasi tidak cocok dengan tipe nilai | Membaca properti dari null atau undefined |
RangeError | Nilai di luar rentang yang diizinkan | Digit toFixed lebih dari 100 |
ReferenceError | Mengakses nama yang tidak pernah dideklarasikan | Salah ketik nama variabel |
SyntaxError | Teks tidak sah secara tata bahasa | JSON.parse menemui string bukan JSON |
Berkas berikut memicu keempatnya secara nyata, satu per satu, lalu mencatat name dan message-nya:
// keluarga-galat.js
// Empat turunan Error yang paling sering ditemui, dipicu satu per satu.
function selidiki(label, aksi) {
try {
aksi();
} catch (error) {
console.log(label + " -> " + error.name + ": " + error.message);
}
}
selidiki("membaca properti dari null", () => {
const keranjang = null;
return keranjang.total;
});
selidiki("angka di luar batas", () => {
(10).toFixed(101);
});
selidiki("variabel tidak pernah dideklarasikan", () => {
return totalBelanja;
});
selidiki("JSON rusak", () => {
JSON.parse("{ tidak valid }");
});Output yang Dihasilkan:
membaca properti dari null -> TypeError: Cannot read properties of null (reading 'total')
angka di luar batas -> RangeError: toFixed() digits argument must be between 0 and 100
variabel tidak pernah dideklarasikan -> ReferenceError: totalBelanja is not defined
JSON rusak -> SyntaxError: Expected property name or '}' in JSON at position 2 (line 1 column 3)Mari kita telaah polanya:
- Baris 12–15 (
selidiki("membaca properti dari null", ...)): callback membacakeranjang.totaldarinull, sehingga engine melemparTypeError. Pesannya presisi:(reading 'total')menyebut properti apa yang dicoba dibaca dari nilai apa. - Baris 17–19 (
selidiki("angka di luar batas", ...)):toFixedhanya menerima digit0sampai100; permintaan101di luar rentang itu memicuRangeError. Kelas galat yang sama muncul untuk panjang array negatif danrepeatdengan hitungan minus. - Baris 21–23 (
selidiki("variabel tidak pernah dideklarasikan", ...)):totalBelanjatidak pernah dideklarasikan, sehingga pencarian nama gagal —ReferenceError: totalBelanja is not defined. Pesan seperti ini hampir selalu berarti salah ketik. - Baris 25–27 (
selidiki("JSON rusak", ...)):JSON.parsemenolak{ tidak valid }karena nama properti JSON wajib diapit tanda kutip ganda. Catatan menarik: galat parsing yang terjadi saat program berjalan tetap berupaSyntaxError— bedanya dengan chapter pertama, galat ini terlempar saat runtime dan bisa ditangkap. - Baris 4–10 (
function selidiki(label, aksi) { ... }): helper kecil ini mengemas pola pemeriksaan: jalankanaksi(), tangkap galatnya, cetaknamedanmessage. Tanpa helper, kita perlu empat bloktry-catchterpisah.
Mengenali jenis galat ini mempercepat diagnosis. ReferenceError mengarah ke kesalahan penulisan nama; TypeError mengarah ke nilai null/undefined yang belum dijaga; RangeError mengarah ke argumen di luar batas.
Selain keempatnya, spesifikasi masih menyiapkan EvalError dan URIError, tetapi keduanya jarang kita temui di kode modern — engine saat ini hampir tidak melemparnya lagi, dan daftar empat di atas sudah menutup hampir semua kejadian sehari-hari.
Cara membaca tabel di atas juga perlu dibalik: keempat jenis itu dilempar engine, sedangkan yang kita tulis sendiri sejauh ini adalah Error generik lewat new Error(...). Pembagian kerjanya jelas — galat perilaku bahasa diserahkan ke engine dengan jenisnya yang presisi, sementara pelanggaran aturan aplikasi kita lempar sendiri. Ketika kebutuhannya makin spesifik, chapter Custom Errors menunjukkan cara membuat jenis baru dengan name milik aplikasi.
cause: Merekam Akar Masalah #
Sering kali sebuah galat adalah akibat dari galat lain: parsing konfigurasi gagal karena JSON-nya rusak. Tanpa perekaman, galat pembungkus hanya bisa menulis konteksnya di message sebagai teks, dan galat asalnya terputus dari rantai. Sejak ES2022, constructor Error menerima argumen kedua berupa object opsi, dan properti cause-nya menyimpan galat asal:
function bacaPengaturan(json) {
try {
return JSON.parse(json);
} catch (error) {
throw new Error("Pengaturan gagal dibaca", { cause: error });
}
}
try {
bacaPengaturan("{ masih rusak }");
} catch (error) {
console.log(error.message);
console.log("Penyebab:", error.cause.name, "-", error.cause.message);
}Output yang Dihasilkan:
Pengaturan gagal dibaca
Penyebab: SyntaxError - Expected property name or '}' in JSON at position 2 (line 1 column 3)Pola di atas menangkap galat asli, membungkusnya dengan pesan konteks yang lebih bermakna, lalu menyimpan galat aslinya utuh di error.cause. Pemanggil di lapisan atas bisa memilih: cukup baca message, atau telusuri cause bila perlu diagnosis lebih dalam. Dengan begitu konteks lapisan atas dan detail lapisan bawah sama-sama terjaga di satu object.
Jenis galat bawaan mencakup banyak kebutuhan, tetapi semuanya generik. TypeError tidak memberi tahu apakah yang gagal itu kupon, saldo, atau sesi login — semua hanya “bukan tipe yang cocok”. Chapter berikutnya menunjukkan cara membuat jenis galat milik aplikasi sendiri, lengkap dengan name yang bermakna, sehingga penanganan bisa memutuskan berdasarkan jenis kegagalan yang sebenarnya.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
keluarga-galat.js
Unduh berkas// keluarga-galat.js
// Empat turunan Error yang paling sering ditemui, dipicu satu per satu.
function selidiki(label, aksi) {
try {
aksi();
} catch (error) {
console.log(label + " -> " + error.name + ": " + error.message);
}
}
selidiki("membaca properti dari null", () => {
const keranjang = null;
return keranjang.total;
});
selidiki("angka di luar batas", () => {
(10).toFixed(101);
});
selidiki("variabel tidak pernah dideklarasikan", () => {
return totalBelanja;
});
selidiki("JSON rusak", () => {
JSON.parse("{ tidak valid }");
});