Ilustrasi sampul artikel: Hoisting JavaScript Adalah? Penjelasan Lengkap untuk Pemula (var, let, const)
·JavaScriptDasarTutorial

Hoisting JavaScript Adalah? Penjelasan Lengkap untuk Pemula (var, let, const)

Hoisting JavaScript adalah perilaku mengangkat deklarasi ke atas scope. Pahami var vs let/const, Temporal Dead Zone, dan function hoisting lewat diagram dan contoh kode.

Pembuat Hyper Sheets & BelajarWeb.dev

Hoisting JavaScript adalah perilaku di mana JavaScript “mengangkat” deklarasi variabel dan fungsi ke bagian atas scope-nya sebelum kode benar-benar dijalankan. Yang diangkat hanyalah deklarasinya, bukan pemberian nilainya. Itulah kenapa kamu kadang bisa memakai sesuatu sebelum baris di mana ia ditulis, dan kadang malah dapat error yang bikin bingung. Memahami hoisting membuat banyak keanehan JavaScript tiba-tiba masuk akal, terutama perbedaan perilaku antara var, let, const, dan fungsi.

Di panduan ini kamu akan belajar apa itu hoisting dari nol: apa persisnya yang “diangkat”, kenapa var menghasilkan undefined alih-alih error, apa itu Temporal Dead Zone (TDZ) yang membuat let dan const melempar ReferenceError, serta kenapa function declaration bisa dipanggil sebelum didefinisikan sementara function expression tidak. Semua dengan contoh kode berbahasa Indonesia yang bisa langsung kamu coba di console browser.

Apa Itu Hoisting?

Sebelum menjalankan kodemu, JavaScript melakukan satu langkah persiapan: ia memindai seluruh scope dan “mencatat” semua deklarasi variabel dan fungsi terlebih dahulu. Secara konsep, deklarasi-deklarasi ini seolah dipindahkan ke atas scope-nya. Proses inilah yang disebut hoisting (dari kata hoist = mengangkat).

Poin yang paling sering disalahpahami: yang diangkat cuma deklarasi, bukan assignment (pemberian nilai). Perhatikan contoh ini:

console.log(pesan)  // undefined, bukan error!
var pesan = "halo"
console.log(pesan)  // "halo"

Baris pertama tidak error, padahal pesan seolah dipakai sebelum dibuat. Alasannya: JavaScript membaca kode di atas seakan-akan seperti ini:

var pesan            // deklarasi diangkat ke atas (nilainya undefined)
console.log(pesan)   // undefined
pesan = "halo"       // assignment TETAP di posisi aslinya
console.log(pesan)   // "halo"

Deklarasi var pesan naik ke atas, tapi = "halo" tetap di barisnya semula. Karena itu di baris pertama variabelnya sudah “ada” tapi belum berisi apa-apa, sehingga bernilai undefined.

Apa yang “Diangkat” saat Hoisting?

Tidak semua hal diangkat dengan cara yang sama. Ada tiga kategori yang berbeda perilakunya, dan inilah sumber kebingungan terbesar seputar hoisting:

  • var, diangkat dan langsung diberi nilai awal undefined. Bisa diakses sebelum baris deklarasi (hasilnya undefined).
  • Function declaration (function nama() {}), diangkat utuh beserta isinya. Bisa dipanggil bahkan sebelum baris di mana ia ditulis.
  • let dan const, diangkat, tapi belum diberi nilai dan belum boleh diakses sampai baris deklarasinya dieksekusi.

Diagram di bawah menunjukkan bagaimana JavaScript “menata ulang” sebuah potongan kode setelah hoisting, deklarasi mana yang naik ke atas, dan bagian mana yang terkunci di zona terlarang:

Cara JS membaca kodemu
Kode yang kamu tulis
console.log(pesan)   // undefined
var pesan = "halo"

sapa()               // ✓ jalan
function sapa() { ... }

console.log(umur)    // ❌ ReferenceError
let umur = 22
Cara JS membacanya (setelah hoisting)
// deklarasi diangkat ke atas ↑
var pesan = undefined
function sapa() { ... }

TDZ dimulai, umur belum bisa diakses
console.log(pesan)   // undefined
sapa()               // ✓ jalan
console.log(umur)    // ❌ ReferenceError
umur = 22 // TDZ selesai di sini
var, diangkat & diisi undefinedfunction, diangkat utuh (bisa dipanggil lebih awal)let / const, diangkat tapi terkunci di TDZ

Perhatikan di panel kanan: var pesan dan function sapa() naik ke atas, sedangkan let umur diangkat tapi terperangkap di zona berwarna, itulah Temporal Dead Zone yang akan kita bahas sebentar lagi.

var vs let/const: Ini Inti Perbedaannya

Ketiga kata kunci sebenarnya sama-sama di-hoist, tapi hasilnya berbeda drastis saat kamu mencoba mengaksesnya sebelum baris deklarasi. Inilah bagian terpenting yang wajib kamu pahami.

Dengan var, mengakses variabel sebelum deklarasi menghasilkan undefined, tidak error, tapi menyesatkan:

console.log(kota)  // undefined (diam-diam, tidak ada peringatan)
var kota = "Bandung"

Dengan let dan const, mengakses variabel sebelum deklarasi melempar ReferenceError yang jelas:

console.log(kota)  // ❌ ReferenceError: Cannot access 'kota' before initialization
let kota = "Bandung"

Berikut tabel ringkas ketiga kata kunci, apakah di-hoist, nilai awalnya apa, dan apa yang terjadi kalau diakses sebelum baris deklarasi:

Kata kunci Di-hoist? Nilai awal saat diangkat Diakses sebelum deklarasi
var Ya undefined Mengembalikan undefined (tidak error)
let Ya belum ada (di TDZ) ReferenceError
const Ya belum ada (di TDZ) ReferenceError
function (declaration) Ya fungsi utuh Bisa dipanggil normal

Temporal Dead Zone (TDZ) Itu Sebenarnya Apa?

TDZ terdengar menakutkan, tapi konsepnya sederhana. Bayangkan sebuah scope dibaca dari atas ke bawah. Untuk let dan const, variabelnya memang sudah “dikenali” sejak awal scope (karena di-hoist), tapi ada aturan: belum boleh disentuh sampai eksekusi mencapai baris deklarasinya. Zona “sudah dikenali tapi belum boleh disentuh” itulah TDZ.

// --- TDZ untuk `nama` dimulai di sini ---
console.log(nama)  // ❌ ReferenceError, masih di dalam TDZ
let nama = "Sari"  // --- TDZ selesai persis di baris ini ---
console.log(nama)  // "Sari", sekarang aman

Begitu eksekusi melewati let nama = "Sari", TDZ berakhir dan variabel bisa dipakai normal. Meskipun terlihat merepotkan dibanding var yang “tidak rewel”, TDZ sebenarnya menyelamatkanmu: ia mengubah bug diam-diam (undefined yang menjalar entah ke mana) menjadi error yang langsung menunjuk lokasi masalah.

Function Declaration vs Function Expression

Fungsi juga mengalami hoisting, tapi caranya bergantung pada bagaimana kamu menulisnya, dan ini perbedaan yang sangat praktis.

Function declaration diangkat secara utuh beserta isinya, sehingga bisa dipanggil bahkan sebelum baris definisinya:

sapa()  // "Halo!", jalan, walaupun dipanggil sebelum didefinisikan

function sapa() {
  console.log("Halo!")
}

Function expression (fungsi yang disimpan ke variabel) dan arrow function tidak bisa. Yang di-hoist hanyalah variabelnya, mengikuti aturan var/let/const, bukan fungsinya:

sapa()  // ❌ TypeError: sapa is not a function

var sapa = function () {
  console.log("Halo!")
}

Di contoh kedua, var sapa diangkat dan bernilai undefined saat sapa() dipanggil. Karena undefined bukan fungsi, JavaScript melempar TypeError. Kalau kamu memakai let atau const untuk function expression, hasilnya ReferenceError karena masih berada di TDZ.

Kenapa Ini Penting untuk Kode Sehari-hari?

Mungkin kamu bertanya: kalau begitu, apakah aku harus repot memikirkan urutan hoisting setiap menulis kode? Jawaban praktisnya: tidak, kalau kamu memakai kebiasaan yang benar. Deklarasikan variabel dan fungsi sebelum kamu memakainya, dan pakai let/const alih-alih var. Dengan begitu, kalau kamu tidak sengaja memakai sesuatu terlalu awal, JavaScript langsung memberi error yang jelas, bukan undefined yang menyelinap diam-diam.

Hoisting sangat erat kaitannya dengan pemilihan kata kunci variabel. Kalau kamu belum mantap soal kapan memakai var, let, atau const, baca dulu perbedaan var, let, dan const yang membahas scope, reassign, dan hoisting secara berdampingan, itu melengkapi apa yang kamu pelajari di sini.

Kesalahan Umum Seputar Hoisting

Beberapa jebakan yang paling sering menimpa pemula:

1. Mengira seluruh baris var x = 5 diangkat. Yang diangkat cuma var x, bukan = 5. Karena itu console.log(x) sebelum baris tersebut menghasilkan undefined, bukan 5.

2. Menyangka let dan const tidak di-hoist. Keduanya tetap di-hoist, bedanya mereka masuk ke TDZ dan melempar error kalau diakses terlalu awal, bukan mengembalikan undefined.

3. Memanggil function expression sebelum definisinya. const jumlah = () => {} tidak bisa dipanggil sebelum barisnya. Hanya function jumlah() {} (declaration) yang bisa.

4. Bingung antara undefined dan ReferenceError. var yang diakses lebih awal memberi undefined; let/const yang diakses lebih awal memberi ReferenceError. Keduanya sinyal berbeda untuk masalah yang mirip.

console.log(a)  // undefined
var a = 1

console.log(b)  // ❌ ReferenceError
let b = 2
Cek Pemahaman

Apa yang dicetak oleh console.log(x) pada baris pertama kode berikut? console.log(x); var x = 5;

FAQ Seputar Hoisting JavaScript

Apa itu hoisting dengan bahasa sederhana?

Hoisting adalah perilaku JavaScript yang “mengangkat” deklarasi variabel dan fungsi ke atas scope sebelum kode dijalankan. Yang diangkat hanya deklarasinya, bukan pemberian nilainya. Itulah sebabnya kamu kadang bisa memakai sesuatu sebelum baris di mana ia ditulis, meski hasilnya bisa undefined atau bahkan error, tergantung apakah kamu memakai var, let, const, atau fungsi.

Apakah let dan const di-hoist?

Ya, let dan const tetap di-hoist. Bedanya dengan var, keduanya tidak langsung diberi nilai undefined. Mereka masuk ke area bernama Temporal Dead Zone (TDZ) sejak awal scope sampai baris deklarasinya. Mengakses variabel di dalam TDZ menghasilkan ReferenceError, bukan undefined. Jadi anggapan bahwa let/const “tidak di-hoist” itu keliru, mereka di-hoist, hanya saja belum boleh diakses.

Apa itu Temporal Dead Zone?

Temporal Dead Zone (TDZ) adalah rentang waktu antara awal scope sampai baris deklarasi sebuah variabel let atau const. Selama berada di TDZ, variabelnya sudah dikenali oleh JavaScript (karena di-hoist) tapi belum boleh diakses. Mencoba membacanya menghasilkan ReferenceError: Cannot access '...' before initialization. TDZ ini fitur yang disengaja agar kamu tidak memakai variabel sebelum ia siap.

Kenapa function declaration bisa dipanggil sebelum didefinisikan?

Karena function declaration (function nama() {}) di-hoist secara utuh, baik namanya maupun isi fungsinya, ke atas scope. Jadi saat kamu memanggilnya di baris manapun dalam scope yang sama, fungsinya sudah tersedia. Ini berbeda dengan function expression (const nama = function () {}) atau arrow function, di mana yang di-hoist hanya variabelnya, sehingga memanggilnya sebelum baris definisi akan error.

Setelah Ini, Belajar Apa?

Menguasai hoisting adalah fondasi penting untuk memahami cara kerja JavaScript di balik layar. Berikut langkah lanjutan yang masuk akal:

  1. Perbedaan var, let, const, hoisting adalah salah satu dari tiga pembeda utamanya. Perdalam scope dan reassign lewat panduan perbedaan var, let, dan const.
  2. Dasar-dasar JavaScript, kalau kamu masih baru, mantapkan variabel, tipe data, dan fungsi di panduan apa itu JavaScript.
  3. Praktik langsung, teori hoisting akan benar-benar melekat kalau kamu langsung mencobanya. Kerjakan materi scope dan hoisting interaktif di Hyper Sheets yang memberi umpan balik instan setiap kali kamu salah, langsung di browser tanpa setup.

Kuncinya bukan menghafal istilah, tapi membangun kebiasaan: deklarasikan sebelum dipakai, pakai const/let, dan biarkan error muncul dengan lantang. Dengan begitu hoisting berubah dari “keanehan JavaScript” menjadi alat yang membantumu menangkap bug lebih awal. Untuk latihan bertahap yang langsung bisa kamu kerjakan, lanjutkan ke pelajaran scope & hoisting di Hyper Sheets.