fbpx

JavaScript VAR, LET, CONST probléma és a HOISTING

2021-04-30

JavaScript VAR, LET, CONST probléma, plusz a HOISTING

 

A JavaScript már lassan 25 éve velünk élő programozási nyelv. Kezdeti botladozásaihoz képest óriás fejlődésen ment át.

A nyelvi fejlődés talán legnagyobb lépcsője az ES6 (egységesített JavaScript szabvány) megjelenése 2015-ben.

Új funkciók, új objektum-orientált megközelítés, osztályok, paraméteres sztringek, iterátorok, generátorok és még számtalan újdonság.

A fejlesztőknek ugyan volt ideje megismerkedni ezekkel az újdonságokkal, de nem mind vették erre fáradtságot. Ebben a kis cikkben két egyszerű nyelvi bővítést szeretnénk bemutatni. Az ES6 verzióval érkező LET és CONST változó deklarálási kulcsszavakat.

Legtöbben elintézték a VAR = LET elképzeléssel és a  – CONST meg azt jelenti, mint a neve, azaz konstans – gondolattal a két kifejezés működését. Ha eddig Te is így gondoltad, akkor olvasd el az alábbi cikket.

 

Kezdjük az elején, volt valaha a var…

 

Az ES6 előtt az egyetlen deklarálási lehetőséget a VAR kulcsszó használata jelentette a JavaScriptben. A deklaráció hatóköre (scope-ja) globális. Amennyiben függvényen belül használjuk, akkor lokális. Ez azt jelenti, ha függvényen kívül deklarálunk var kulcsszóval, akkor a teljes kódra érvényes változót kapunk.

 

var developer = "George";

function testFunc() {
    var tester = "Peter";
}

 

Ebben a kis kódban a developer változó globális hatókörrel bír, a tester pedig lokális a testFunc() függvény blokkjában.

 

var developer = "George";

function testFunc() {
    var tester = "Peter";
}

console.log(tester);

 

Ha megpróbáljuk a tester változót a testFunc() függvényen kívül használni, akkor hibával megáll a script futása. A tester hatóköre nem terjed ki függvényblokkon kívülre.

Uncaught ReferenceError: tester is not defined

Uncaught ReferenceError: tester is not defined

 

A VAR kulcsszóval definiált változó természetesen megváltoztatható, ami azonban meglepőbb, hogy újra is deklarálható.

 

var developer = "George";
developer = "Peter"

 

Az-az gond nélkül lefut a következő kód is:

 

var developer = "George";
var developer = "Peter";
console.log(developer);

 

 

Peter

 

A program fejlesztése során ilyen újradeklarációval ritkán élünk. Inkább elvárás, hogy álljon le a script ebben az esetben (várható, hogy tévedésből használjuk újra a már deklarált változót). Ez a működés hibához vezethet.

 

HOISTING

 

A VAR kulcsszóval kapcsolatban gyakran halljuk a HOISTING jelenség kifejezést. Nézzük mit is jelent.

console.log(developer);

 

console.log(developer);

 

 

Hibára fut. Ami természetes.

 

Uncaught ReferenceError: developer is not defined

 

 

Az érdekes kérdés az, hogy mi történik, ha ezután a sor után deklaráljuk a developer változót.

 

 

console.log(developer);
var developer = "George";

 

 

Ebben az esetben a script simán lefut és a konzolra azt írja, hogy: undefined.

Mi is történik ebben az esetben? A scriptet az értelmező úgy futtatja, hogy a globális hatókörben talált deklarációt fölemeli a script tetejére. A lefutás kronológia sorrendje ez alapján így néz ki:

 

 

var developer;
console.log(developer);
developer = "George";

 

Ezt a futtatási működést hívjuk HOISTING (emelés) jelenségnek. A script futtatása, az utasítások sorrendjének változása miatt megtréfálhatja a fejlesztőt. Ez a helyzetet úgy tudjuk elkerülni, hogy a scriptek elejére tesszük a változó a deklarációkat (gyakorlatilag kiiktatjuk a HOISTING mechanizmust).

 

Nézzünk egy problémásabb helyzetet a VAR kulcsszóval. A VAR által lehetővé tett újradeklaráció abban az esetben is működik, ha egy beágyazott struktúrában történik.

 

var message = "Everything is alright.";
var eventCounter = 0;
if (eventCounter < 1) {
    var message = "Nothing is wrong.";
}
console.log(message)

 .

Nothing is wrong

 

 Az if struktúrában felvett message változó deklaráció fölüldeklarálja a globális hatókörön lévő message változót. Ez újabb hibalehetőség a kódolás során.

 

 

Nézzük miben más a LET!

 

A LET működését és szintaktikáját tekintve nagyon hasonlít a VAR-ra. A különbség két fontos ponton jelenik meg.

Az egyik az újradeklarálhatóság megszüntetése.

 

let developer = "George";
let developer = "Peter";

 

Uncaught SyntaxError: Identifier 'developer' has already been declared

 
 

A másik fontos különbség a LET-tel deklarált változó hatókörében van.

 

let message = "Everything is alright.";
let eventCounter = 0;
if (eventCounter < 1) {
    let message = "Nothing is wrong.";
}
console.log(message);

 

Everything is alright.

 

Ahogy a fenti kis példán látszik, a beágyazott blokkban történő újradeklarálás nem okoz hibát, a script hiba nélkül lefut. Ezzel együtt azonban azt is fontos látni, hogy a globális hatókörben létrehozott message változó értékét nem változtatja meg, és nem deklarálja fölül. A beágyazott blokkban lévő message változó csak a blokkon belül értelmezett. Az az a különbség a hatókörben van. LET esetén ez egy „block scope” (kódblokkon belüli hatókör). Ez természetesebb működést jelent. A blokkon belül LET-tel deklarált változó a blokk futásának idejére elfedi a globális változót. A blokk vége után visszaáll a blokk előtti helyzet, ahogy az a következő kis programból látszik:

 

let message = "Everything is alright.";
let eventCounter = 0;
if (eventCounter < 1) {
    let message = "Nothing is wrong.";    console.log(message);
}
console.log(message);

 

Nothing is wrong.
Everything is alright.

 

 

A CONST ahogy a neve is mutatja

 

A CONST kulcsszó szintén deklarációra használható. A vele létrehozott változó értéke nem változtatható, így helyesebb ha konstansnak nevezzük. Érvényességét tekintve a LET-re hasonlít legjobban, hiszen „block scope” érvényességű a létrehozott konstans. Amiben mégis különböző a LET-tel létrehozott változótól, hogy ebben az esetben a változó értéke sem írható fölül. A következő kód ezért hibát eredményez:

 

const developer = "George";
developer = "Peter";

 

 

Uncaught TypeError: Assignment to constant variable.

 

 

Összefoglalva

 

 Összehasonlítás

Hatókör

Újra deklarálhatóság

Új érték adás

Hoisting

 VAR

Globális/Lokális

Igen

Igen

Igen

 LET

Blokk

Nem

Igen

Igen

 CONST

Blokk

Nem

Nem

Igen

 

A jó döntés a LET használata minden esetben, amikor nem dedikált cél a változó hatókörének kiterjesztése! (A VAR teljes elfelejtését azonban nem javaslom, hiszen például egy for ciklus blokkjában deklarált értéket esetleg a ciklus után is lekérdeznénk.)

 

Kapcsolódó tanfolyamunk: