Budi menulis program kecil penghitung harga. Pada percobaan pertama, perintah node program.js berakhir tanpa satu baris pun dieksekusi — Node hanya menampilkan SyntaxError. Pada percobaan kedua dengan berkas yang sudah dia perbaiki, program justru mencetak dua baris hasil lalu berhenti mendadak di tengah jalan. Dua kegagalan itu tampak serupa di layar, padahal terjadi pada fase yang berbeda dan menuntut cara membaca yang berbeda pula.
Chapter ini memicu kedua jenis galat secara sengaja, lalu membaca transkrip yang Node tampilkan. Tujuannya satu: ketika galat serupa menimpa program kita sendiri, kita langsung tahu fase mana yang bermasalah dan mulai mencari dari mana.
Dua Fase: Parsing dan Eksekusi #
Sebelum program berjalan, engine JavaScript membaca seluruh berkas dan mengubah teksnya menjadi struktur yang bisa dieksekusi. Tahap pembacaan ini disebut parsing. Bila teksnya tidak mengikuti tata bahasa JavaScript — tanda kutip yang tidak ditutup, kurung yang hilang, kata kunci di tempat yang salah — parser menolak seluruh berkas dan melaporkan SyntaxError.
Baru setelah parsing selesai tanpa hambatan, program dijalankan baris demi baris. Galat yang muncul pada tahap ini disebut galat runtime: sintaksnya sah, tetapi sesuatu pada data atau alur membuat satu baris tidak dapat dikerjakan — misalnya membaca properti dari undefined.
Perbedaan fase ini bukan sekadar jargon. Galat parsing selalu berarti masalah pada teks program — apa yang kita ketik — sedangkan galat runtime berarti masalah pada data dan alur saat program berjalan. Karena itu keduanya punya lokasi pencarian yang berbeda: satu di kode sumber, satu lagi di nilai yang dibawa ke baris bermasalah.
| Aspek | Galat parsing | Galat runtime |
|---|---|---|
| Kapan terjadi | Saat berkas dibaca, sebelum eksekusi | Saat program berjalan |
| Baris yang terlanjur dieksekusi | Tidak ada sama sekali | Semua baris sebelum baris bermasalah |
| Contoh penyebab | Tanda kutip tidak ditutup | Membaca properti dari undefined |
| Contoh pesan | SyntaxError: Invalid or unexpected token | TypeError: Cannot read properties of undefined (reading 'harga') |
Galat Parsing: Program Tidak Pernah Berjalan #
Aturan yang perlu dipegang: satu kesalahan tanda baca cukup untuk menolak seluruh berkas. Tidak ada eksekusi “setengah jalan” — parser harus sukses membaca semua baris terlebih dahulu, baru baris pertama dijalankan.
Berkas berikut sengaja memuat string yang tanda kutipnya tidak ditutup. Perhatikan baris 4: isinya sudah benar dan tidak bersalah apa pun:
// galat-parsing.js
// Demonstrasi: galat parsing - program tidak pernah berjalan.
console.log("Program dimulai");
const pesan = "Halo;
console.log(pesan);Jika berkas ini dijalankan, tidak ada satu baris pun yang dieksekusi. Node berhenti di tahap parsing dan menampilkan transkrip berikut (path dipendekkan):
/home/…/galat-parsing.js:6
const pesan = "Halo;
^^^^^^
SyntaxError: Invalid or unexpected tokenMari kita baca transkrip itu:
- Baris pertama (
/home/…/galat-parsing.js:6): Node menyebut lokasi kegagalan — berkasgalat-parsing.js, baris 6. - Baris kedua (
const pesan = "Halo;): Node menampilkan isi baris 6 apa adanya, lalu baris^^^^^^menunjuk bagian yang membuat parser gagal: string yang tidak pernah ditutup. - Pesan akhir (
SyntaxError: Invalid or unexpected token): laporan parser bahwa token di posisi itu tidak sah.
Yang paling penting: teks Program dimulai tidak pernah tercetak. Baris 4 sudah benar, tetapi parser menilai seluruh berkas sebelum mengeksekusi baris mana pun — satu baris rusak membuat semuanya tidak jalan.
Galat sintaks lain berlaku serupa. Sebagai contoh, const tanpa nilai awal juga ditolak parser — dan kali ini kita memeriksanya tanpa menjalankan apa pun, memakai opsi node --check berkas.js yang hanya membaca sintaks:
const angka;SyntaxError: Missing initializer in const declarationOpsi node --check berguna ketika kita hanya ingin memastikan sintaks benar sebelum program dijalankan: parser melaporkan temuannya, dan tidak ada satu baris pun dieksekusi.
Galat Runtime: Berjalan, lalu Berhenti di Tengah #
Sekarang berkas dengan sintaks yang sepenuhnya sah, tetapi berisi data yang membuat satu baris tidak dapat dikerjakan. Fungsi hargaProduk membaca produk dari object katalog; masalah muncul ketika nama yang dicari tidak ada:
// galat-runtime.js
// Demonstrasi: galat runtime - program berjalan, lalu berhenti di tengah.
console.log("Program dimulai");
const katalog = {
"Kabel USB": { stok: 24, harga: 25000 },
"Buku Catatan": { stok: 40, harga: 15000 },
};
function hargaProduk(nama) {
const item = katalog[nama];
return item.harga;
}
console.log(hargaProduk("Kabel USB"));
console.log(hargaProduk("Penghapus"));
console.log("Program selesai");Ketika dijalankan, dua baris pertama tercetak, lalu program berhenti dan Node menampilkan transkrip galat (path dipendekkan; baris internal engine diringkas):
Program dimulai
25000
/home/…/galat-runtime.js:13
return item.harga;
^
TypeError: Cannot read properties of undefined (reading 'harga')
at hargaProduk (/home/…/galat-runtime.js:13:15)
at Object.<anonymous> (/home/…/galat-runtime.js:17:13)
at Module._compile (node:internal/modules/cjs/loader:1929:14)
... 6 baris internal engine lainnya ...
Node.js v24.21.0Pola berhentinya berbeda dari galat parsing. Mari kita telusuri:
- Baris 4 (
console.log("Program dimulai")): dieksekusi normal — bukti bahwa parsing sukses dan program benar-benar berjalan. - Baris 12 (
const item = katalog[nama];): saat dipanggil dengan"Penghapus", lookupkatalog["Penghapus"]menghasilkanundefined— akses key yang tidak ada pada object tidak menimbulkan galat, jadiitemdiam-diam berisiundefined. - Baris 13 (
return item.harga;): di sinilah program gagal. Membaca properti dariundefinedtidak mungkin dikerjakan, sehingga engine melemparTypeErrordan eksekusi berhenti di baris ini. - Baris 17 (
console.log(hargaProduk("Penghapus"))): frameat Object.<anonymous>pada transkrip menunjuk baris ini — pemanggil yang membawa galat naik ke permukaan. - Baris 19 (
console.log("Program selesai")): tidak pernah tercapai. Berbeda dari galat parsing, baris sebelum titik gagal tetap sudah dijalankan.
Satu detail kecil pada transkrip layak dicatat: Node mengakhiri program dengan kode keluar (exit code) 1, bukan 0. Kode 0 adalah tanda program selesai normal; kode selain itu menandakan kegagalan. Skrip shell dan alat otomatis membaca kode ini untuk memutuskan apakah langkah sebelumnya berhasil — karenanya galat yang dibiarkan naik sampai ke Node tetap terdeteksi dari luar program.
Cara Cepat Membedakan Keduanya #
Kuncinya pada satu pertanyaan: apakah ada keluaran tercetak sebelum galat muncul? Bila tidak ada sama sekali, galat terjadi saat parsing — periksa tanda baca dan sintaks di baris yang ditunjuk. Bila ada keluaran lalu program berhenti, galat terjadi saat runtime — periksa data yang dibawa ke baris tersebut.
Kedua skenario Budi di pembuka chapter kini terbaca jelas: percobaan pertamanya gagal karena teks program tidak sah untuk parser, dan percobaan keduanya gagal karena data yang mengalir membuat baris tertentu tidak dapat dikerjakan. Penulisan program nyata hampir selalu bergantian di antara dua situasi itu, dan kebiasaan membaca transkrip dengan pola di atas memangkas waktu pencarian secara nyata.
Kedua jenis galat ini berhenti begitu saja karena belum ada penangkapnya. Chapter berikutnya membahas cara kita yang melempar galat secara sengaja lewat throw, sebelum akhirnya kita belajar menangkapnya.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
galat-parsing.js
Unduh berkas// galat-parsing.js
// Demonstrasi: galat parsing - program tidak pernah berjalan.
console.log("Program dimulai");
const pesan = "Halo;
console.log(pesan);
galat-runtime.js
Unduh berkas// galat-runtime.js
// Demonstrasi: galat runtime - program berjalan, lalu berhenti di tengah.
console.log("Program dimulai");
const katalog = {
"Kabel USB": { stok: 24, harga: 25000 },
"Buku Catatan": { stok: 40, harga: 15000 },
};
function hargaProduk(nama) {
const item = katalog[nama];
return item.harga;
}
console.log(hargaProduk("Kabel USB"));
console.log(hargaProduk("Penghapus"));
console.log("Program selesai");