Press "Enter" to skip to content

Variable, Scope dan Hoisting Pada Javascript

Variabel
Sebelum menggunakan sebuah variabel pada program Javascript, variabel tersebut haruslah dideklarasikan terlebih dahulu. Variabel dideklarasikan menggunakan kata-kunci var, seperti berikut:

var i;
var sum;

Beberapa buah variabel dapat juga dideklarasikan sekaligus menggunakan sebuah kata kunci var :

var i, sum;

Deklarasi variabel dapat dikombinasikan dengan inisialisasi variabel:

var pesan; //deklarasi variabel
pesan = “halo”; //inisialisasi variabel

var pesan = “halo”; //deklarasi sekaligus inisialisasi variabel
var i = 0, j = 0, k = 0; //deklarasi sekaligus inisialisasi beberapa variabel

Jika sebuah variabel dideklarasikan tanpa menginisialisasi value, maka value dari variabel tersebut adalah undefined, dan akan tetap undefined hingga value lain disimpan kedalam variabel tersebut.

(pada cli node.js)

var x;
undefined
x;
undefined

Sebagai catatan, pernyataan var juga muncul sebagai bagian dari loop for dan for/in. Hal ini guna meringkas deklarasi variabel loop, variabel juga merupakan bagian dari sintaks loop itu sendiri.

for(var i = 0; i < 10; i++) console.log(i);

Bagi yang terbiasa dengan bahasa seperti Java atau C, akan menyadari bahwa tidak ada tipe yang berhubungan dengan deklarasi variabel Javascript. Variabel Javascript dapat menyimpan berbagai tipe value. Sebagai contoh, pada Javascript samasekali tidak menjadi masalah jika mengalokasikan sebuah nomor kedalam variabel lalu mengalokasikan string kepada variabel yang sama.

var i = 10;
i = “sepuluh”;

Jika sebuah value dialokasikan pada variabel yang belum dideklarasikan maka Javascript akan menjadikan variabel tersebut sebagai properti dari global objek dan variabel bekerja seperti global variabel yang terdeklarasi. Hal ini bermakna global variabel bisa saja digunakan tanpa dideklarasikan terlebih dahulu, namun hal ini merupakan kebiasaan buruk dan sumber bug, sebaiknya tetap deklarasikan variabel menggunakan var.

i = 10; // i adalah properti global objek dan merupakan variabel global karena tidak dideklarasikan.

Scope Variabel
Scope dari sebuah variabel adalah wilayah dari source code program dimana variabel ditetapkan. Sebuah global variabel memiliki scope global, yaitu diperuntukan bagi seluruh source code, sebaliknya, variabel yang dideklarasikan dalam fungsi terbatas hanya dalam body dari fungsi tersebut.

Dalam body dari sebuah fungsi, variabel lokal memiliki hak lebih tinggi daripada global variabel dengan nama yang sama, jika sebuah variabel lokal atau parameter dideklarasikan dengan nama yang sama dengan global variabel, maka global variabel akan disembunyikan.

var scope = “global”; //deklarasi dan inisialisasi global variabel
function testscope() {
var scope = “lokal”; //deklarasi dan inisialisasi variabel lokal dengan nama yang sama
return scope; //mengembalikan value lokal, bukan global
}

testscope() //hasilnya adalah “lokal”

Meskipun pada saat menulis code di scope global dapat saja tanpa menggunakan var, namun untuk variabel lokal var harus selalu digunakan untuk mendeklarasikan variabel lokal, apa yang terjadi jika hal ini diabaikan?

scope = “global”; //menginisialisasi scope tanpa deklarasi, menjadikan scope sebagai variabel global
function testscope() {
scope = “lokal”; //perhatikan! value global variabel berubah!
scopeSaya = “lokal”; //global variable baru
return [scope, scopeSaya];
}

testscope();
[‘lokal’, ‘lokal’]
scope
‘lokal’
scopeSaya
‘lokal’

Fungsi dapat berada didalam fungsi lain, oleh karena itu setiap fungsi memiliki scope lokal sendiri:

var scope = “global scope” //variabel global
function testscope() {
var scope = “scope lokal”;
function dalamScope() {
var scope = “scope dalam”;
return scope;
}
return dalamScope();
}

testscope(); // “scope dalam”

Hoisting
Scope fungsi pada Javascript artinya semua variabel yang di deklarasikan dalam sebuah fungsi terlihat dalam body dari fungsi tersebut, uniknya, variabel bahkan terlihat sebelum di deklarasikan, fitur Javascript ini dikenal dengan nama hoisting, yaitu code Javascript berprilaku seolah-olah semua deklarasi variabel dalam sebuah fungsi “diangkat” menuju bagian paling atas dari fungsi. Perhatikan code berikut:

var scope = “global”;
function f() {
console.log(scope); //undefined, bukan global
var scope = “lokal”; //inisialisasi variabel
console.log(scope); // “lokal”
}

Fungsi diatas serupa dengan fungsi berikut, dimana deklarasi variabel “diangkat” kebagian paling atas dari fungsi, namun inisialisasi tetap ditempatnya semula.

function f() {
var scope; //variabel lokal di deklarasikan pada bagian atas dari fungsi;
console.log(scope); // undefined, variabel memiliki value undefined karena belum inisialisasi
scope = “lokal”; //menginisialisasi variabel
console.log(scope); // value yang diharapkan “lokal”
}

Block Scope
ES6 (2015) memperkenalkan kata kunci let dan const untuk mendeklarasikan variabel. variabel yang dideklarasikan menggunakan let adalah block-scoped, hanya ada dalam block. variabel yang dideklarasikan menggunakan var adalah function-scope. contoh berikut memperlihatkan block-scoped:

var x = 1;
{let x = 2;
console.log(x); //2
}
console.log(x); //1

Pada pendeklarasian block-scoped variabel, dianjurkan untuk meletakan deklarasi let pada bagian paling atas block. Perhatikan contoh berikut:

function barter(a, b) { //function scope
if (a>0 && b>0) { //block scope
let temporer = a;
a = b;
b = temporer;
} //block scope berakhir
console.log(a, b);
console.log(temporer); //undefined, karena berada pada block scope
return [a, b];
}
barter(1,2);

Scope Chain
Tiap kumpulan code pada Javascript (code global atau fungsi) memiliki sebuah rantai scope (scope chain) yang terkait dengannya. Rantai scope ini adalah sebuah daftar atau rantai objek yang menetapkan/menegaskan variabel-variabel yang berada dalam scope untuk kode tersebut.

Saat Javascript ingin mengetahui value dari variabel x (proses ini disebut resolusi variabel), ia akan memulai dengan mencarinya pada objek pertama pada rantai, jika objek tersebut memiliki properti bernama x, maka value dari objek tersebut akan digunakan, jika objek pertama itu tidak memiliki properti bernama x, Javascript akan melanjutkan pencarian pada objek selanjutnya pada rantai, jika objek kedua tidak memiliki properti x, pencarian berlanjut pada objek berikut, begitu seterusnya. Jika x bukan properti dari objek manapun pada rantai, maka x tidak berada dalam scope code tersebut, dan terjadilah ReferenceError.

var x = 1;
function z() {
var y = 1;
return x;
}
z();
1
y;
ReferenceError: y is not defined

Dari contoh diatas diambil kesimpulan didalam z(), y dan x terlihat, diluar z(), x terlihat namun y tidak terlihat.

Jika sebuah fungsi terdalam() bernaung didalam fungsi terluar(), terdalam() dapat mengakses variabel pada scopenya, ditambah scope induknya.

Pada top-level code Javascript (contohnya: code yang tidak berada dalam fungsi manapun) rantai scope terdiri dari sebuah objek tunggal, yaitu global objek. Pada sebuah fungsi yang tidak bernaung pada fungsi lain, rantai scope terdiri dari 2 objek. Yang pertama adalah objek yang menetapkan parameter fungsi dan variabel lokal, dan yang kedua adalah global objek. Pada fungsi yang bernaung, ia memiliki 3 objek atau lebih, penting untuk memahami bagaimana rantai objek ini dibuat.

Saat sebuah fungsi ditetapkan, fungsi ini akan menyimpan rantai scope, saat fungsi ini dipanggil, fungsi ini membuat objek baru guna menyimpan variabel lokal miliknya, lalu memasukan objek baru tersebut ke penyimpanan rantai scope, hal ini akan menghasilkan rantai baru yang lebih panjang yang merepresentasikan scope bagi pemanggilan fungsi tersebut. Menariknya, tiap kali fungsi terluar dipanggil maka fungsi didalam akan ditetapkan ulang. Karena rantai scope berbeda pada tiap pemanggilan fungsi terluar, fungsi bagian dalam akan sedikit berbeda tiap kali ditetapkan, yaitu code fungsi bagian dalam akan identik setiap pemanggilan fungsi terluar, namun rantai scope code terkait akan berubah. Ide rantai scope ini penting untuk memahami closure.

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.