Definisanje varijabli u JavaScriptu - var, let ili const
Tags: javascript, webdev, es6
Published: 2022-12-28 17:00:13

**Postoji više načina da se definiše varijabla u JavaScriptu. Nešto stariji način je korištenjem ključne riječi `var`. Međutim, ES6 standard JavaScripta je donio dvije nove ključne riječi za definisanje varijabli - `let` i `const`. U ovom tekstu ćete pročitati najosnovnije razlike između ova tri pristupa.**

_Kratka napomena: Tokom cijelog ovog teksta ću koristiti riječ varijabla, čak i u slučaju kada pričam o vrijednosti koja je ona definisana sa `const` koja u suštini znači da je definisana vrijednost u suštini konstanta. Više o razlici između to dvoje u četvrtom poglavlju ovog teksta._


### Šta će se sve moći pročitati u ovom tekstu?

- Razlika između var i let u opsegu
- Razlika između var i let u hoistingu
- Razlika u ponovnom deklarisanju
- Razlika između let i const

---


#### Razlika između `var` i `let` u opsegu (scope)

_Šta je opseg?_


Opseg je okruženje u kom je neka deklarisana vrijednost vidljiva. U JavaScriptu postoje tri opsega: globalni, funkcijski i blok.

Sve vrijednosti koje su deklarisane u globalnom opsegu su dostupne u cijelom programu. Bez obzira koja ključna riječ je korištena prilikom deklarisanja ta vrijednost će biti vidljiva u cijelom programu.

![example code of JavaScript global scope](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z93r4xfw8xumeu3jka6i.png)

Dakle, bilo gdje u kodu imate pristup varijabli `name` jer je ona ima globalni opseg. Funkcija `logName` i `console.log` imaju pristup varijabli `name`.

Generalno govoreći treba izbjegavati deklarisanje globalnih varijabli, jer to otvara prostor za pojavljivanje različitih preklapanja i/ili poništavanja za drugim skriptama i bibliotekama.

U ovom kontekstu važno je naglasiti da će svaka varijabla koja je deklarisana bez ključne riječi automatski postati globalna varijabla.


![automatic global variable js example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4eiiha8jjmcdwxtm8d7f.png)

Razlika između var i let dolazi u tome kada one nisu globalne varijable. Varijable deklarisane sa `var` imaju opseg funkcije u kojoj su deklarisane.

![JavaScript function scope example code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n4a4jp4l2bwpydjkrxs4.png)

Šta se dešava? Kada pozovete funkciju `logName` ona vidi varijablu `ime` jer opseg varijable `ime` je ta funkcija. Međutim, kada pokušate da pristupite toj varijabli u `console.log(ime)` tu ste već u globalnom opsegu i nemate pristup (ne vidite) varijabli `ime`, te ćete zato dobiti grešku.

Za razliku od ovoga varijable deklarisane sa `let` imaju opseg _bloka koda_. Blok koda u JavaScriptu je jednostavno rečeno sve što se nalazi unutar vitičastih zagrada `{}`. To može biti `if-else` izjava, `switch` izjava, bilo koja petlja...

![JavaScript block scope example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j726fvz222v0jlqgq75n.png)

Šta se dešava? Imam `if` izjavu (blok koda) unutar koje je deklarisanja varijabla `ime`. Unutar istog tog bloka koda `console.log(ime)` će viditi tu varijablu jer opseg te varijable je taj blok koda. Međutim, izvan ovog bloka ste u globalnom opsegu i nemate pristup varijabli `ime`.

Varijabla deklarisana sa `var` ovdje ne bi izbacila grešku.


![JavaScript example block scope code with var](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1bajdiwn99s9qnfbpama.png)

Varijabla `ime` bi u ovom slučaju imala globalni opseg i bila bi dostupna (vidljiva) drugoj `console.log(ime)` izjavi.



---


#### Razlika između `var` i `let` u hoistingu

Još jedna od razlika između `var` i `let` ključne riječi je u ponašanju tokom takozvanog hoisting-a (podizanje). Ovo je mehanizam u kom su deklaracije funkcija i varijabli naizgled pomjerene na vrh (hoist) njihovog opsega. Upravo zbog ovog mehanizma možete imati pristup varijablama ili funkcijama prije njihovog deklarisanja.


![example code for JavaScript var hoisging](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/toa06oaypd2wxoa22t6l.png)


Dakle, funkcija `logName` ima pristup varijabli `ime` zato što je varijabla `ime` **naizgled** podignuta na vrh opsega _(scope - global)_, ali treba obratiti pažnju na to da joj je vrijednost `undefined`.

Upravo ovdje nastupa razlika između `var` i `let`. Ovaj princip hoisting-a će funkcionisati samo sa varijablama koje su deklarisane sa `var`. Ukoliko bi pokušali iskoristiti `let` za deklarisanje varijable dobićete grešku zato što varijable deklarisane sa `let` neće biti podignute.


![example JavaScript code hoisting with let variable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2aju07jr8brd34ayauv5.png)

Riječ 'naizgled' je namjerno označena jer upravo tu dolazi objašnjenje. Ništa se ne podiže, prilikom egzekucije koda nijedna linija koda neće u stvari biti pomjerena. Podizanje je samo 'naizgled'.

##### Šta JavaScript engine radi kada čita kod?

Kada neki engine (komponenta koja je zadužena za izvršenje JavaScript koda) čita JavaScript kod on obavlja dva koraka: faza kreacije (creation phase) i faza izvršenja (execution phase).

1. U fazi kreiranja 'engine' deklariše svaku varijablu, dodijeli joj prostor u memoriji i početnu vrijednost `undefined`. Tada je varijabla deklarisana. Ovo je _deklaracija_ varijable.

2. U fazi izvršenja varijabla će dobiti vrijednost koja joj je dodijeljena u kodu. Npr. kada napišete `var ime = 'Slaven'` Ovo je _inicijalizacija_ varijable.

Mehanizam podizanja će podići samo deklaraciju varijable, ali ne i inicijalizaciju. Upravo zbog ovoga varijable deklarisane sa `var` imaju vrijednost `undefined` kada pokušate da ih iskoristite prije inicijalizacije.

Međutim varijablama koje su deklarisane sa `let` ne možete pristupiti prije inicijalizacije (drugi korak) i zato ćete dobiti grešku `ReferenceError` ako pokušate da je iskoristite prije inicijalizacije. U suštini 'engine' vam govori: 'Vidim varijablu, deklarisana je, ali nije inicijalizovana i zato joj ne možete pristupiti'.

_Napomena: Strogo govoreći varijable deklarisane sa `let` i `const` između ova dva koraka završavaju u nečemu što se zove 'temporal dead zone' (vremenska mrtva zona), objašnjenje toga bi zahtjevalo malo dublje obješanjenje faze kreacije i egzekucije (izvršenja), te sam smatrao da bi to trebalo biti tema za neki drugi tekst._

---

#### Razlika u ponovnom deklarisanju

Još jedna od razlika je u tome što varijable deklarisane sa `var` mogu biti ponovo deklarisane sa istim imenom.


![example code of JavaScript redeclaration with var](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tr4w58ivnppudegqr0i6.png)

Ovo je validna JavaScript sintaksa ako se koristi `var`. Druga deklaracija će poništiti prvu i zato će varijabla `ime` nositi vrijednost 'John'.

Očigledno je koliko je ovo potencijalno problematično. Ne želite se naći u situaciji gdje nakon izvjesnog vremena pokušate ponovo deklarisati varijablu zato što ste možda zaboravili da već imate varijablu sa istim imenom.

Promjenu u ovom kontekstu došle su sa `let` (kao i `const`). Varijable deklarisane sa `let` ne mogu biti ponovo deklarisane i dobićete grešku.


![example JavaScript code for redeclaration with let](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h7per7t4g8q8p3yiyu3o.png)

Ovo će izbaciti grešku `SyntaxError` istog trenutka kada dođe do ponovo deklarisane varijable.


---


#### Razlika između `let` i `const`

Varijable deklarisane sa `let` i `const` ponašaju identično u svim slučajevima o kojim sam govorio do sada (opseg, podizanje, ponovna deklaracija).

Razlika između ove dvije ključne riječi je u tome što varijablama koje su deklarisane sa `let` mogu dodijeliti novu vrijednost negdje drugo dok varijable koje su deklarisane sa `const` to ne dozvoljavaju i to je svrha njihovog uvođenja.


![example JavaScript code for value change with let](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eeut5rmlgxncnulldc7q.png)

Ovo ne treba pomiješati sa onim što sam govorio u prethodnom poglavlju da `let` varijable ne mogu biti ponovo deklarisane. Ovdje varijabla `ime` nije ponovo deklarisana nego joj je samo dodijeljena druga vrijednost.

Međutim, ključna riječ `const` ovo ne dozvoljava.


![example JavaScript code for redeclaration with const](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vnko6wgu8rckmc201bwg.png)

Ovo nije dozvoljeno i dobićete grešku istog trenutka kada dođe do ponovnog dodjeljivanja vrijednosti. Kao što navedena greška kaže, nije dozvoljeno dodjeljivati vrijednost konstantama.

Jedna stvar na koju treba obratiti pažnju kod `const` varijabli je to kako se one ponašaju kada nose vrijednost referentnih tipova podataka, kao što su objekti ili nizovi. Iako ni ovdje nije dozvoljeno ponovo dodjeljivati vrijednost, dozvoljeno je mijenjati same elemente unutar te vrijednosti.


![example of JavaScript code for const object property change](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v5pmwdngpqb1oedobf6b.png)

Ovdje imamo objekat `korisnik` koji ima dva svojstva. Nakon toga je promijenjeno svojstvo `godine` u tom objektu.

Ovo je dozvoljeno u JavaScriptu čak i sa `const` varijablama. Ovo se naziva mutacija varijabli. Dakle, dozvoljeno je mijenjati pojedinačna svojstva unutar objekta, ali nije dozvoljeno ponovo dodijeliti vrijednost cijeloj varijabli.

Postoje načini da se zamrznu neka svojstva u objektima, ali to je tema koju vrijedi ispitadi u zasebnom tekstu.


---

#### Zaključak

- Izbjegavajte korištenje globalnih varijabli. Ovo otvara previše prostora za preklapanje naziva varijabli iz različitih skripti ili biblioteka.

- Uglavnom bi trebalo izbjeći korištenje `var` ključne riječi za deklarisanje varijabli sada kada imamo na raspolaganju `let` i `const`. Varijable sa `var` prljaju globalni (window) objekat, a to je poželjno izbjeći.

- Koristite `const` za deklarisanje varijabli ako možete predviditi da ta varijabla neće dobijati drugu vrijednost. Ako imate razloga da mislite da će nekad tokom njenog korištenja ta varijabla dobiti drugu vrijednost slobodno možete koristiti `let` ključnu riječ.