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"; |
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"; |
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"; |
Az-az gond nélkül lefut a következő kód is:
var developer = "George"; |
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); |
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; |
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."; |
.
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"; |
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."; |
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."; |
Nothing is wrong. |
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"; |
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:
Az egész tanfolyam szuper jól volt felépítve.