Variabel

Variabel adalah struktur data yang menetapkan nama perwakilan ke nilai. Data dapat berisi data apa pun.

Nama variabel disebut ID. ID yang valid harus mengikuti aturan berikut:

  • ID dapat berisi huruf Unicode, tanda dolar ($), karakter garis bawah (_), angka (0-9), dan bahkan beberapa karakter Unicode.
  • ID tidak boleh berisi spasi kosong, karena parser menggunakan spasi kosong untuk memisahkan elemen input. Misalnya, jika Anda mencoba memanggil variabel my Variable, bukan myVariable, parser akan melihat dua ID, my dan Variable, dan menampilkan error sintaksis ("token yang tidak terduga: ID").
  • ID harus diawali dengan huruf, garis bawah (_), atau tanda dolar ($). ID tidak boleh diawali dengan angka, untuk mencegah kebingungan antara angka dan ID:

    let 1a = true;
    
    > Uncaught SyntaxError: Invalid or unexpected token
    

    Jika JavaScript mengizinkan angka di awal ID, hal itu akan mengizinkan ID yang hanya terdiri dari angka, sehingga menyebabkan konflik antara angka yang digunakan sebagai angka dan angka yang digunakan sebagai ID:

    let 10 = 20
    
    10 + 5
    > ?
    
  • "Kata yang dicadangkan" yang sudah bermakna secara sintaksis tidak dapat digunakan sebagai ID.

  • ID tidak boleh berisi karakter khusus (! . , / \ + - * =).

Berikut ini bukan aturan ketat untuk membuat ID, tetapi merupakan praktik terbaik industri yang mempermudah pemeliharaan kode Anda. Jika project tertentu Anda memiliki standar yang berbeda, ikuti standar tersebut untuk konsistensi.

Dengan mengikuti contoh yang ditetapkan oleh metode dan properti bawaan JavaScript, camel case (juga bergaya "camelCase") adalah konvensi yang sangat umum untuk ID yang terdiri dari beberapa kata. Camel case adalah praktik menggunakan huruf besar pada huruf pertama setiap kata kecuali yang pertama untuk meningkatkan keterbacaan tanpa spasi.

let camelCasedIdentifier = true;

Beberapa project menggunakan konvensi penamaan lain, bergantung pada konteks dan sifat data. Misalnya, huruf pertama class biasanya menggunakan huruf besar, sehingga nama class multi-kata sering menggunakan varian camel case yang biasa disebut "upper camel case" atau Pascal case.

class MyClass {

}

ID harus menjelaskan sifat data yang dikandungnya secara ringkas (misalnya, currentMonthDays adalah nama yang lebih baik daripada theNumberOfDaysInTheCurrentMonth) dan dibaca dengan jelas secara sekilas (originalValue lebih baik daripada val). ID myVariable yang digunakan di seluruh modul ini berfungsi dalam konteks contoh terisolasi, tetapi akan sangat tidak membantu dalam kode produksi karena tidak memberikan informasi tentang data yang dikandungnya.

ID tidak boleh terlalu spesifik tentang data yang dikandungnya, karena nilainya dapat berubah bergantung pada cara skrip bertindak pada data tersebut, atau pada keputusan yang dibuat oleh pengelola di masa mendatang. Misalnya, variabel yang awalnya diberi ID miles mungkin perlu diubah menjadi nilai dalam kilometer nanti dalam project, sehingga mengharuskan pengelola untuk mengubah referensi apa pun ke variabel tersebut untuk menghindari kebingungan di masa mendatang. Untuk mencegah hal ini, gunakan distance sebagai ID Anda.

JavaScript tidak memberikan hak istimewa atau makna khusus apa pun pada ID yang dimulai dengan karakter garis bawah (_), tetapi biasanya digunakan untuk menunjukkan bahwa variabel, metode, atau properti bersifat "pribadi", yang berarti hanya ditujukan untuk digunakan dalam konteks objek yang berisinya, dan tidak boleh diakses atau diubah di luar konteks tersebut. Ini adalah konvensi yang diwariskan dari bahasa pemrograman lain, dan sudah ada sebelum penambahan properti pribadi JavaScript.

Deklarasi variabel

Ada beberapa cara untuk membuat JavaScript mengetahui ID, yaitu proses yang disebut "mendeklarasikan" variabel. Variabel dideklarasikan menggunakan kata kunci let, const, atau var.

let myVariable;

Gunakan let atau var untuk mendeklarasikan variabel yang dapat diubah kapan saja. Kata kunci ini memberi tahu penafsir JavaScript bahwa string karakter adalah ID yang mungkin berisi nilai.

Saat bekerja di codebase modern, gunakan let, bukan var. var masih berfungsi di browser modern, tetapi memiliki beberapa perilaku yang tidak intuitif yang ditentukan dalam versi JavaScript paling awal, lalu tidak dapat diubah nanti untuk mempertahankan kompatibilitas mundur. let ditambahkan di ES6 untuk mengatasi beberapa masalah dengan desain var.

Variabel yang dideklarasikan diinisialisasi dengan menetapkan nilai ke variabel. Gunakan satu tanda sama dengan (=) untuk menetapkan atau menetapkan ulang nilai ke variabel. Anda dapat melakukannya sebagai bagian dari pernyataan yang sama yang mendeklarasikannya:

let myVariable = 5;

myVariable + myVariable
> 10

Anda juga dapat mendeklarasikan variabel dengan let (atau var) tanpa langsung melakukan inisialisasi. Jika Anda melakukannya, nilai awal variabel adalah undefined hingga kode Anda menetapkan nilainya.

let myVariable;

myVariable;
> undefined

myVariable = 5;

myVariable + myVariable
> 10

Variabel dengan nilai undefined berbeda dengan variabel yang belum ditentukan yang ID-nya belum dideklarasikan. Mereferensikan variabel yang belum Anda deklarasikan akan menyebabkan error.

myVariable
> Uncaught ReferenceError: myVariable is not defined

let myVariable;

myVariable
> undefined

Pengaitan ID dengan nilai umumnya disebut "binding". Sintaksis yang mengikuti kata kunci let, var, atau const disebut "daftar binding", dan memungkinkan beberapa deklarasi variabel yang dipisahkan koma (berakhir dengan titik koma yang diharapkan). Hal ini membuat cuplikan kode berikut secara fungsional identik:

let firstVariable,
     secondVariable,
     thirdVariable;
let firstVariable;
let secondVariable;
let thirdVariable;

Menetapkan ulang nilai variabel tidak menggunakan let (atau var), karena JavaScript sudah mengetahui bahwa variabel tersebut ada:

let myVariable = true;

myVariable
> true

myVariable = false;

myVariable
> false

Anda dapat menetapkan ulang nilai baru variabel berdasarkan nilai yang ada:

let myVariable = 10;

myVariable
> 10

myVariable = myVariable * myVariable;

myVariable
> 100

Jika Anda mencoba mendeklarasikan ulang variabel menggunakan let di lingkungan produksi, Anda akan mendapatkan error sintaksis:

let myVariable = true;
let myVariable = false;
> Uncaught SyntaxError: redeclaration of let myVariable

Alat developer browser lebih permisif terhadap deklarasi ulang let (dan class), sehingga Anda mungkin tidak melihat error yang sama di konsol developer.

Untuk mempertahankan kompatibilitas browser lama, var memungkinkan deklarasi ulang yang tidak perlu tanpa error dalam konteks apa pun:

var myVariable = true;
var myVariable = false;

myVariable\
> false

const

Gunakan kata kunci const untuk mendeklarasikan konstanta, jenis variabel yang harus segera diinisialisasi, lalu tidak dapat diubah. ID untuk konstanta mengikuti semua aturan yang sama seperti variabel yang dideklarasikan menggunakan let (dan var):

const myConstant = true;

myConstant
> true

Anda tidak dapat mendeklarasikan konstanta tanpa langsung menetapkan nilainya, karena konstanta tidak dapat ditetapkan ulang setelah dibuat, sehingga konstanta yang tidak diinisialisasi akan tetap undefined selamanya. Jika Anda mencoba mendeklarasikan konstanta tanpa melakukan inisialisasi, Anda akan mendapatkan error sintaksis:

const myConstant;
Uncaught SyntaxError: missing = in const declaration

Mencoba mengubah nilai variabel yang dideklarasikan dengan const seperti cara Anda mengubah nilai variabel yang dideklarasikan dengan let (atau var) akan menyebabkan error jenis:

const myConstant = true;

myConstant = false;
> Uncaught TypeError: invalid assignment to const 'myConstant'

Namun, saat konstanta dikaitkan dengan objek, properti objek tersebut dapat diubah.

const constantObject = { "firstvalue" : true };

constantObject
> Object { firstvalue: true }

constantObject.secondvalue = false;

constantObject
> Object { firstvalue: true, secondvalue: false }

Konstanta yang berisi objek adalah referensi yang tidak dapat diubah ke nilai data yang dapat diubah. Meskipun konstanta itu sendiri tidak dapat diubah, properti objek yang dirujuk dapat diubah, ditambahkan, atau dihapus:

const constantObject = { "firstvalue" : true };

constantObject = false
> Uncaught TypeError: invalid assignment to const 'constantObject'

Jika Anda tidak ingin variabel ditetapkan ulang, sebaiknya buat variabel tersebut menjadi konstanta. Penggunaan const memberi tahu tim pengembangan atau pengelola project mendatang untuk tidak mengubah nilai tersebut, agar tidak melanggar asumsi yang dibuat kode Anda tentang cara penggunaannya—misalnya, bahwa variabel pada akhirnya akan dievaluasi berdasarkan jenis data yang diharapkan.

Cakupan variabel

Cakupan variabel adalah bagian dari skrip tempat variabel tersebut tersedia. Di luar cakupan variabel, variabel tidak akan ditentukan—bukan sebagai ID yang berisi nilai undefined, tetapi seolah-olah belum dideklarasikan.

Bergantung pada kata kunci yang Anda gunakan untuk mendeklarasikan variabel dan konteks tempat Anda menentukannya, Anda dapat menentukan cakupan variabel untuk memblokir pernyataan (cakupan blok), setiap fungsi (cakupan fungsi), atau seluruh aplikasi JavaScript (cakupan global).

Cakupan blok

Setiap variabel yang Anda deklarasikan menggunakan let atau const dicakupkan ke pernyataan blok terdekat yang berisinya, yang berarti variabel hanya dapat diakses dalam blok tersebut. Mencoba mengakses variabel cakupan blok di luar blok penampung akan menyebabkan error yang sama seperti mencoba mengakses variabel yang tidak ada:

{
    let scopedVariable = true;
    console.log( scopedVariable );
}
> true

scopedVariable
> ReferenceError: scopedVariable is not defined

Sejauh menyangkut JavaScript, variabel cakupan blok tidak ada di luar blok yang berisinya. Misalnya, Anda dapat mendeklarasikan konstanta di dalam blok, lalu mendeklarasikan konstanta lain di luar blok tersebut yang menggunakan ID yang sama:

{
  const myConstant = false;
}
const myConstant = true;

scopedConstant;
> true

Meskipun variabel yang dideklarasikan tidak dapat diperluas ke blok induknya, variabel tersebut tersedia untuk semua blok turunan:

{
    let scopedVariable = true;
    {
    console.log( scopedVariable );
    }
}
> true

Nilai variabel yang dideklarasikan dapat diubah dari dalam blok turunan:

{
    let scopedVariable = false;
    {
    scopedVariable = true;
    }
    console.log( scopedVariable );
}
> true

Variabel baru dapat diinisialisasi dengan let atau const di dalam blok turunan tanpa error, meskipun menggunakan ID yang sama dengan variabel dalam blok induk:

{
    let scopedVariable = false;
    {
    let scopedVariable = true;
    }
    console.log( scopedVariable );
}
> false

Cakupan Fungsi

Variabel yang dideklarasikan menggunakan var dicakup ke fungsi penampung terdekatnya (atau blok inisialisasi statis di dalam class).

function myFunction() {
    var scopedVariable = true;

    return scopedVariable;
}

scopedVariable;
> ReferenceError: scopedVariable is not defined

Hal ini tetap berlaku setelah fungsi dipanggil. Meskipun variabel diinisialisasi saat fungsi dieksekusi, variabel tersebut masih tidak tersedia di luar cakupan fungsi:

function myFunction() {
    var scopedVariable = true;

    return scopedVariable;
}

scopedVariable;
> ReferenceError: scopedVariable is not defined

myFunction();
> true

scopedVariable;
> ReferenceError: scopedVariable is not defined

Cakupan global

Variabel global tersedia di seluruh aplikasi JavaScript, di dalam semua blok dan fungsi, ke skrip apa pun di halaman.

Meskipun ini tampak seperti default yang diinginkan, variabel yang dapat diakses dan diubah oleh bagian aplikasi apa pun dapat menambahkan overhead yang tidak perlu, atau bahkan menyebabkan tabrakan dengan variabel di tempat lain dalam aplikasi dengan ID yang sama. Hal ini berlaku untuk semua JavaScript yang terlibat dalam rendering halaman, termasuk hal-hal seperti library pihak ketiga dan analisis pengguna. Oleh karena itu, sebaiknya hindari mencemari cakupan global jika memungkinkan.

Setiap variabel yang dideklarasikan menggunakan var di luar fungsi induk, atau menggunakan let atau const di luar blok induk, bersifat global:

var functionGlobal = true; // Global
let blockGlobal = true; // Global

{
    console.log( blockGlobal );
    console.log( functionGlobal );
}
> true
> true

(function() {
    console.log( blockGlobal );
    console.log( functionGlobal );
}());
> true
> true

Menetapkan nilai ke variabel tanpa mendeklarasikannya secara eksplisit (yaitu, dengan tidak pernah menggunakan var, let, atau const untuk membuatnya) akan meningkatkan variabel ke cakupan global, meskipun diinisialisasi di dalam fungsi atau blok. Variabel yang dibuat menggunakan pola ini terkadang disebut "global tersirat".

function myFunction() {
    globalVariable = "global";

    return globalVariable
}

myFunction()\
> "global"

globalVariable\
> "global"

Pengangkatan Variabel

Deklarasi variabel dan fungsi ditarik ke bagian atas cakupannya, yang berarti bahwa penafsir JavaScript memproses variabel apa pun yang dideklarasikan pada titik mana pun dalam skrip dan secara efektif memindahkannya ke baris pertama cakupan penyertanya sebelum menjalankan skrip. Artinya, variabel yang dideklarasikan menggunakan var dapat direferensikan sebelum variabel dideklarasikan tanpa mengalami error:

hoistedVariable
> undefined

var hoistedVariable;

Karena hanya deklarasi variabel yang dihosting, bukan inisialisasi, variabel yang belum dideklarasikan secara eksplisit dengan var, let, atau const tidak diangkat:

unhoistedVariable;
> Uncaught ReferenceError: unhoistedVariable is not defined

unhoistedVariable = true;

Seperti yang disebutkan sebelumnya, variabel yang dideklarasikan tetapi tidak diinisialisasi diberi nilai undefined. Perilaku tersebut juga berlaku untuk deklarasi variabel yang diangkat, tetapi hanya untuk deklarasi yang dideklarasikan menggunakan var.

hoistedVariable
> undefined

var hoistedVariable = 2 + 2;

hoistedVariable\
> 4

Perilaku yang tidak intuitif ini sebagian besar merupakan sisa dari keputusan desain yang dibuat di versi JavaScript paling awal, dan tidak dapat diubah tanpa risiko merusak situs yang ada.

let dan const mengatasi perilaku ini dengan menampilkan error saat variabel diakses sebelum dibuat:

{
    hoistedVariable;

    let hoistedVariable;
}
> Uncaught ReferenceError: can't access lexical declaration 'hoistedVariable' before initialization

Error ini berbeda dengan error "hoistedVariable is not defined" yang mungkin Anda harapkan saat mencoba mengakses variabel yang tidak dideklarasikan. Karena JavaScript telah mengangkat variabel, JavaScript mengetahui bahwa variabel akan dibuat dalam cakupan yang diberikan. Namun, alih-alih menyediakan variabel tersebut sebelum deklarasinya dengan nilai undefined, penafsir akan menampilkan error. Variabel yang dideklarasikan dengan let atau const (atau class) dikatakan berada di "zona mati temporal" ("TDZ") dari awal blok yang melingkupinya hingga titik dalam kode tempat variabel dideklarasikan.

Zona mati temporal membuat perilaku let lebih intuitif daripada var untuk penulis. Hal ini juga penting untuk desain const. Karena konstanta tidak dapat diubah, konstanta yang diangkat ke bagian atas cakupannya dan diberi nilai implisit undefined tidak dapat diinisialisasi dengan nilai yang bermakna.

Memeriksa pemahaman Anda

Jenis karakter apa yang dapat Anda gunakan untuk memulai ID?

Surat
Garis bawah
Digit

Manakah metode yang lebih disukai untuk mendeklarasikan variabel yang nilainya dapat diubah kapan saja?

let
const
var