Perbedaan Var, Let, dan Const yang Masih Sering Membingungkan

Dalam ekosistem JavaScript, deklarasi variabel adalah salah satu fundamental yang paling sering menjadi sumber kebingungan, terutama bagi yang baru belajar atau yang terbiasa dengan versi JavaScript lama. Sebelum ES6 (ECMAScript 2015) hadir, kita hanya memiliki satu cara untuk mendeklarasikan variabel: var. Namun, setelah ES6, muncul dua pemain baru yang mengubah lanskap: let dan const.

Meskipun ketiganya berfungsi untuk menyimpan nilai, perbedaan perilaku antara var, let, dan const sangat signifikan dan mempengaruhi cara kode Anda berjalan, kejelasan, serta potensi bug. Memahami nuansa ini bukan sekadar pengetahuan teknis, melainkan esensial untuk menulis kode JavaScript modern, bersih, dan mudah di-maintain. Mari kita bongkar satu per satu.

Memahami Var: Warisan JavaScript Lama

var adalah metode deklarasi variabel yang sudah ada sejak awal JavaScript. Meskipun masih berfungsi, banyak developer modern memilih untuk tidak lagi menggunakannya karena beberapa perilakunya yang seringkali menimbulkan masalah tak terduga.

Function Scope: Ciri Khas Var

Salah satu karakteristik utama var adalah function scope. Ini berarti sebuah variabel yang dideklarasikan dengan var hanya bisa diakses di dalam fungsi tempat ia dideklarasikan, atau secara global jika dideklarasikan di luar fungsi manapun. Ia tidak memiliki block scope, yang berarti variabel var tidak akan terbatas pada blok kode seperti if statement atau for loop.

Perhatikan contoh berikut:

function contohVar() {
if (true) {
var pesan = "Halo dunia!";
console.log(pesan); // Output: Halo dunia!
}
console.log(pesan); // Output: Halo dunia! (Variabel 'pesan' masih bisa diakses di luar blok if)
}
contohVar();
// console.log(pesan); // ReferenceError: pesan is not defined (di luar fungsi)

Dalam praktiknya, perilaku ini seringkali menyebabkan variabel “bocor” dari blok kode yang seharusnya membatasinya, membuat debugging menjadi lebih sulit dan meningkatkan risiko konflik nama variabel.

Hoisting: Sisi Gelap Var

var memiliki perilaku hoisting yang unik. Ketika Anda mendeklarasikan variabel dengan var, deklarasinya diangkat ke bagian atas scope-nya (fungsi atau global) saat kompilasi. Namun, inisialisasi (pemberian nilai awal) tidak ikut diangkat. Ini berarti Anda bisa mengakses variabel var bahkan sebelum dideklarasikan, tetapi nilainya akan undefined.

console.log(nama); // Output: undefined
var nama = "Tubianto";
console.log(nama); // Output: Tubianto

Perilaku hoisting ini seringkali membingungkan dan dapat menimbulkan bug yang sulit dideteksi, karena kode terlihat benar secara sekuensial tetapi memiliki perilaku yang berbeda saat runtime.

Dapat Dideklarasikan Ulang dan Diperbarui

Variabel var juga bisa dideklarasikan ulang dalam scope yang sama tanpa error, dan nilainya bisa diperbarui kapan saja.

var angka = 10;
console.log(angka); // Output: 10

var angka = 20; // Dideklarasikan ulang
console.log(angka); // Output: 20

angka = 30; // Diperbarui
console.log(angka); // Output: 30

Fleksibilitas ini, meskipun kadang berguna, seringkali menjadi bumerang dalam proyek besar atau tim, di mana deklarasi ulang yang tidak disengaja dapat menimpa nilai variabel lain dan menyebabkan bug.

Memperkenalkan Let: Era Baru Deklarasi Variabel

let diperkenalkan di ES6 sebagai pengganti var yang lebih modern dan memiliki perilaku yang lebih prediktif. Mayoritas developer saat ini menggunakan let sebagai pilihan utama ketika nilai variabel perlu diubah.

Block Scope: Perubahan Fundamental

Berbeda dengan var, variabel yang dideklarasikan dengan let memiliki block scope. Ini berarti variabel let hanya dapat diakses dalam blok kode (misalnya, di dalam if statement, for loop, atau blok kurung kurawal {}) tempat ia dideklarasikan.

function contohLet() {
if (true) {
let pesan = "Halo dari Let!";
console.log(pesan); // Output: Halo dari Let!
}
// console.log(pesan); // ReferenceError: pesan is not defined (di luar blok if)
}
contohLet();

Perilaku block scope ini adalah salah satu alasan utama mengapa let jauh lebih disukai daripada var. Kode menjadi lebih modular, lebih mudah dipahami, dan risiko variabel tumpang tindih berkurang drastis.

Hoisting yang Lebih Baik (Temporal Dead Zone)

let juga mengalami hoisting, tetapi dengan cara yang lebih ketat dibandingkan var. Variabel let di-hoist, namun tidak diinisialisasi dengan undefined. Ini menciptakan apa yang disebut Temporal Dead Zone (TDZ). Artinya, Anda tidak bisa mengakses variabel let sebelum dideklarasikan.

// console.log(produk); // ReferenceError: Cannot access 'produk' before initialization (TDZ)
let produk = "Laptop Gaming";
console.log(produk); // Output: Laptop Gaming

TDZ memaksa developer untuk mendeklarasikan variabel sebelum menggunakannya, sehingga mengurangi potensi bug yang disebabkan oleh hoisting yang kurang jelas pada var.

Dapat Diperbarui, Tidak Dapat Dideklarasikan Ulang

Variabel let dapat diperbarui (nilainya diubah) setelah dideklarasikan, tetapi tidak dapat dideklarasikan ulang dalam scope yang sama.

let harga = 15000;
console.log(harga); // Output: 15000

harga = 20000; // Diperbarui
console.log(harga); // Output: 20000

// let harga = 25000; // SyntaxError: Identifier 'harga' has already been declared

Pembatasan ini mencegah kesalahan tidak disengaja berupa deklarasi ulang variabel, yang dapat menyebabkan perilaku yang tidak diinginkan dalam kode.

Memperkenalkan Const: Untuk Nilai yang Konstan

const juga diperkenalkan di ES6, dan tujuannya adalah untuk mendeklarasikan konstanta—nilai yang tidak akan berubah selama lifetime program. const memiliki banyak kesamaan dengan let, tetapi dengan batasan yang lebih ketat.

Block Scope: Sama Seperti Let

Seperti let, variabel yang dideklarasikan dengan const juga memiliki block scope. Ini berarti ia hanya dapat diakses dalam blok kode tempat ia dideklarasikan.

function contohConst() {
if (true) {
const API_KEY = "xyz123";
console.log(API_KEY); // Output: xyz123
}
// console.log(API_KEY); // ReferenceError: API_KEY is not defined
}
contohConst();

Konstanta: Tidak Dapat Diperbarui maupun Dideklarasikan Ulang

Ini adalah perbedaan paling krusial dari const. Setelah variabel const diberi nilai, nilainya tidak dapat diubah (diperbarui) atau dideklarasikan ulang. Selain itu, variabel const harus diinisialisasi saat deklarasi.

// const PI; // SyntaxError: Missing initializer in const declaration
const PI = 3.14;
console.log(PI); // Output: 3.14

// PI = 3.14159; // TypeError: Assignment to constant variable.
// const PI = 3.1; // SyntaxError: Identifier 'PI' has already been declared

Aturan ini membuat const sangat ideal untuk nilai-nilai yang memang tidak seharusnya berubah, seperti konstanta matematika, konfigurasi, atau elemen DOM yang hanya diambil sekali.

Yang Perlu Diperhatikan: Objek dan Array pada Const

Ada satu detail penting tentang const yang seringkali membingungkan developer. Ketika Anda mendeklarasikan objek atau array dengan const, yang tidak dapat diubah adalah referensi ke objek/array tersebut, bukan isi dari objek/array itu sendiri.

Artinya, Anda tidak bisa menetapkan objek/array baru ke variabel const tersebut, tetapi Anda bisa mengubah properti objek atau elemen array di dalamnya.

const user = { nama: "Budi", usia: 25 };
console.log(user); // Output: { nama: 'Budi', usia: 25 }

user.usia = 26; // Ini boleh dilakukan!
console.log(user); // Output: { nama: 'Budi', usia: 26 }

// user = { nama: "Ani", usia: 30 }; // TypeError: Assignment to constant variable. (Ini tidak boleh!)

Begitu juga dengan array:

const angka = [1, 2, 3];
console.log(angka); // Output: [1, 2, 3]

angka.push(4); // Ini boleh dilakukan!
console.log(angka); // Output: [1, 2, 3, 4]

// angka = [5, 6, 7]; // TypeError: Assignment to constant variable. (Ini tidak boleh!)

Poin ini sangat penting untuk diingat agar tidak salah memahami fungsi const saat bekerja dengan tipe data referensi.

Tabel Perbandingan Singkat: Var, Let, dan Const

Untuk memudahkan pemahaman, berikut ringkasan perbandingan:

  • Scope:
    • var: Function scope
    • let: Block scope
    • const: Block scope
  • Hoisting:
    • var: Hoisted, diinisialisasi dengan undefined.
    • let: Hoisted, tetapi dalam Temporal Dead Zone (TDZ).
    • const: Hoisted, tetapi dalam Temporal Dead Zone (TDZ).
  • Dapat Dideklarasikan Ulang:
    • var: Ya
    • let: Tidak
    • const: Tidak
  • Dapat Diperbarui (Reassignment):
    • var: Ya
    • let: Ya
    • const: Tidak (kecuali untuk properti objek/elemen array)
  • Harus Inisialisasi Saat Deklarasi:
    • var: Tidak
    • let: Tidak
    • const: Ya

Kapan Menggunakan Var, Let, dan Const? (Best Practices)

Mengikuti best practices dalam mendeklarasikan variabel sangat penting untuk menulis kode yang bersih dan terhindar dari bug.

Var: Hindari Sebisa Mungkin

Sebagai seorang developer modern, saya sangat menyarankan untuk menghindari penggunaan var sama sekali. Perilaku function scope dan hoisting-nya yang “lunak” seringkali menjadi sumber bug yang sulit dideteksi, terutama dalam kode yang kompleks atau kolaboratif. let dan const memberikan kontrol yang lebih baik dan perilaku yang lebih prediktif.

Const: Default Anda

Gunakan const sebagai pilihan pertama Anda untuk mendeklarasikan variabel. Mengapa? Karena sebagian besar nilai yang kita gunakan dalam program tidak dimaksudkan untuk berubah. Dengan menggunakan const, Anda secara eksplisit menyatakan bahwa sebuah nilai bersifat konstan, yang membuat kode lebih mudah dibaca, dipahami, dan di-debug. Jika Anda mencoba mengubah nilai const, JavaScript akan segera memberitahu Anda dengan error, mencegah bug potensial.

Let: Jika Memang Perlu

Jika Anda tahu bahwa nilai sebuah variabel akan berubah di kemudian hari (misalnya, counter di loop, variabel yang di-reassign berdasarkan kondisi tertentu), barulah gunakan let. Ini adalah sinyal yang jelas bagi developer lain (dan diri Anda sendiri di masa depan) bahwa nilai variabel ini bersifat dinamis dan akan diperbarui. Ingat, gunakan let hanya jika ada kebutuhan yang jelas untuk melakukan reassignment.

Pengalaman dan Pertimbangan Praktis Developer

Sebagai seorang software engineer yang sehari-hari menulis kode JavaScript, beralih dari kebiasaan menggunakan var ke let dan const di awal ES6 memang butuh adaptasi. Namun, manfaatnya sangat terasa:

  • Debugging Lebih Mudah: Dengan block scope pada let dan const, saya jarang lagi mengalami masalah variabel yang “bocor” secara tidak terduga. Lingkup variabel menjadi lebih jelas, sehingga melacak asal-usul nilai menjadi lebih cepat.
  • Kode Lebih Prediktif: Menggunakan const secara default membuat kode saya lebih prediktif. Ketika saya melihat sebuah variabel dideklarasikan dengan const, saya tahu saya tidak perlu khawatir nilai tersebut akan diubah di bagian lain dari blok kode. Ini mengurangi beban kognitif saat membaca kode.
  • Mencegah Kesalahan Umum: Dulu, seringkali saya tidak sengaja mendeklarasikan ulang variabel dengan var dan menimpa nilai penting. let dan const menghilangkan masalah ini dengan langsung memberikan SyntaxError.
  • Mendukung Static Analysis dan Linter: Tools seperti ESLint sangat membantu dalam menegakkan penggunaan let dan const yang benar, serta mendeteksi potensi masalah seperti variabel yang dideklarasikan tapi tidak pernah diubah (yang seharusnya bisa jadi const).

Bagi developer yang bekerja dalam tim, konsistensi dalam penggunaan let dan const juga sangat krusial. Ini membantu semua anggota tim untuk membaca dan memahami kode dengan asumsi yang sama, mengurangi miskomunikasi dan mempercepat proses pengembangan.

Masalah yang Sering Terjadi

Meskipun let dan const jauh lebih baik, ada beberapa masalah umum yang sering dihadapi developer saat menggunakannya:

1. ReferenceError karena Temporal Dead Zone (TDZ)

  • Gejala: Anda mendapatkan error ReferenceError: Cannot access 'variabel' before initialization.
  • Penyebab: Anda mencoba menggunakan variabel let atau const sebelum dideklarasikan (dan diinisialisasi). Ini adalah perilaku TDZ yang disengaja.
  • Solusi: Pastikan Anda selalu mendeklarasikan variabel let atau const di bagian atas blok scope tempat Anda akan menggunakannya, sebelum pemanggilan atau operasi apa pun yang melibatkan variabel tersebut.

2. TypeError: Assignment to constant variable

  • Gejala: Anda mendapatkan error TypeError: Assignment to constant variable.
  • Penyebab: Anda mencoba mengubah nilai (melakukan reassignment) ke variabel yang dideklarasikan dengan const, padahal itu tidak diizinkan untuk tipe data primitif. Atau Anda mencoba menetapkan objek/array baru ke variabel const yang sudah memiliki nilai.
  • Solusi: Jika Anda memang perlu mengubah nilai variabel tersebut, gunakan let alih-alih const. Ingat, untuk objek atau array const, Anda bisa memodifikasi isinya (misal: obj.prop = 'nilai_baru' atau arr.push('item_baru')), tetapi tidak bisa mengganti seluruh objek/array dengan yang baru.

3. Variabel dalam Loop Tidak Sesuai Ekspektasi (dengan var)

  • Gejala: Terutama terlihat pada closure di dalam loop for yang menggunakan var. Misalnya, event listener yang ditambahkan di dalam loop selalu merujuk ke nilai terakhir dari variabel loop.
  • Penyebab: Variabel var yang dideklarasikan dalam loop memiliki function scope atau global scope, sehingga nilai variabel akan diperbarui terus-menerus selama iterasi. Ketika callback di-trigger, ia melihat nilai variabel pada saat loop selesai.
  • Solusi: Gunakan let di dalam loop for. Karena let memiliki block scope, sebuah instance baru dari variabel let akan dibuat untuk setiap iterasi loop, sehingga setiap closure akan menangkap nilai variabel yang benar untuk iterasi tersebut.

FAQ

Apakah var masih boleh digunakan?

Secara teknis, iya, var masih berfungsi di JavaScript. Namun, secara praktis, sangat disarankan untuk tidak lagi menggunakannya di kode modern. let dan const menawarkan kontrol scope yang lebih baik dan perilaku yang lebih prediktif, mengurangi potensi bug.

Apa itu Temporal Dead Zone (TDZ)?

Temporal Dead Zone adalah periode waktu di mana variabel let atau const sudah di-hoist (deklarasinya diketahui oleh JavaScript) tetapi belum diinisialisasi. Selama periode ini, mencoba mengakses variabel akan menghasilkan ReferenceError. Ini memaksa developer untuk mendeklarasikan variabel sebelum menggunakannya.

Kenapa const bisa diubah isinya jika itu objek atau array?

const mencegah reassignment, yaitu tindakan mengubah variabel untuk menunjuk ke nilai atau referensi baru. Namun, untuk objek dan array, const hanya melindungi referensi ke objek/array itu sendiri. Properti di dalam objek atau elemen di dalam array masih bisa dimodifikasi (mutasi) karena Anda tidak mengubah referensi variabel, melainkan konten di dalamnya.

Kesimpulan

Perbedaan antara var, let, dan const adalah salah satu konsep fundamental dalam JavaScript modern. Dengan hadirnya let dan const di ES6, kita mendapatkan tools yang jauh lebih baik untuk mengelola variabel dalam kode kita. let dengan block scope dan kemampuannya untuk di-reassign, serta const dengan block scope dan sifatnya yang tidak dapat di-reassign, memberikan kejelasan, mencegah bug, dan mendorong praktik coding yang lebih baik.

Sebagai developer, mengadopsi const sebagai default dan menggunakan let hanya saat diperlukan adalah best practice yang akan membuat kode Anda lebih mudah dipahami, di-maintain, dan lebih stabil. Tinggalkan var di masa lalu, dan nikmati kemudahan serta prediktabilitas yang ditawarkan oleh let dan const.

TAGS: JavaScript, var, let, const, Scope, Hoisting, ES6, Programming Tutorial, Developer Tools


Baca Juga

You May Also Like

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *