Beruflich Dokumente
Kultur Dokumente
Sintaksa
Ako ste pisali JS kd barem neko vreme, vrlo je verovatno da vam je sintaksa prilino po-
znata. Svakako postoje mnoge posebnosti, ali u optem sluaju, to je prilino smislena i
lako razumljiva sintaksa koja ima mnogo slinosti s drugim jezicima.
Meutim, ES6 uvodi prilian broj novih sintaksnih oblika na koje se treba navii. U
ovom poglavlju emo ih navesti pojedinano da bismo razmotrili ta sve postoji.
(function IIFE(){
var a = 3;
console.log( a ); // 3
})();
console.log( a ); // 2
646
Deklarisanje promenljivih pomou rezervisane rei let
Meutim, sada moemo zadavati deklaracije promenljivih koje su vezane za odreeni
blok, to se (nimalo iznenaujue) zove opseg vidljivosti veliine bloka. To znai da nam
treba samo par { .. } kako bismo definisali opseg vidljivosti. Umesto rezervisane rei var,
koja uvek deklarie promenljive iji je opseg vidljivosti okruujua funkcija (ili globalni
opseg, ako su deklarisane na najviem nivou), zadajte rezervisanu re let:
var a = 2;
{
let a = 3;
console.log( a ); // 3
}
console.log( a ); // 2
U JS-u dosad nije bila mnogo uobiajena upotreba samostalnog bloka { .. }, ali je to
oduvek bila ispravna sintaksa. Taj model e odmah prepoznati programeri iz drugih jezi-
ka u kojima se moe definisati opseg vidljivosti veliine bloka.
Verujem da je to najbolji nain da se deklariu promenljive iji opseg vidljivosti je
blok, unutar vlastitog bloka { .. }. Osim toga, trebalo bi da let deklaraciju (ili deklara-
cije) uvek postavite na poetak tog bloka. Ako treba da deklariete vie promenljivih, pre-
poruio bih vam da zadate samo jedan let.
to se stila pisanja tie, ja ak najradije piem let u istom redu gde je poetna zagra-
da {, kako bih jasnije istakao da je svrha tog bloka samo deklarisanje opsega vidljivosti
tih promenljivih.
{ let a = 2, b, c;
// ..
}
To e izgledati udno i verovatno se nee slagati s preporukama iz veeg dela literatu-
re o ES6. Ali imam dobre razloge za svoju uvrnutost.
Postoji jo jedan eksperimentalan (nestandardizovan) oblik let deklaracije nazvan
let blok, koji izgleda ovako:
let (a = 2, b, c) {
// ..
}
Taj oblik je ono to zovem eksplicitni opseg vidljivosti veliine bloka, dok je oblik let
.. deklaracije koji preslikava oblik var deklaracije vie implicitan, poto nije najjasnije
vidljivo kojem paru { .. } pripada. Programeri uglavnom smatraju da je upotreba ekspli-
citnih mehanizama ipak preporuljivija od implicitnih mehanizama, a ja tvrdim da je ovo
jedan od takvih sluajeva.
Ako uporedite prethodna dva oblika, oni su vrlo slini, a po mom miljenju, oba po
stilu pripadaju eksplicitnom zadavanju opsega vidljivosti veliine bloka. Naalost, oblik
if (a > 1) {
let b = a * 3;
console.log( b ); // 6
let c = a + b;
console.log( c ); // 8
}
Brza provera, bez gledanja u primer: koja promenljiva (ili promenljive) postoji samo
unutar iskaza if, a koja promenljiva (ili promenljive) postoji samo unutar petlje for?
Odgovori: iskaz if sadri promenljive b i c iji je opseg vidljivosti blok iskaza if, a pet-
lja for sadri promenljive i i j iji je opseg vidljivosti blok petlje.
Da li ste morali da razmiljate izvesno vreme? Iznenauje li vas to to promenljiva i
nije dodata u opseg vidljivosti bloka svog okruujeeg iskaza if? Razlog te mentalne pa-
uze i pitanja ja to zovem mentalna taksa potie od injenice da taj let mehanizam
ne samo to je za nas novina, nego je i implicitan.
injenica da se deklaracija let c = .. nalazi tako duboko unutar opsega vidljivosti
uvodi i odreenu opasnost. Za razliku od promenljivih koje deklariete na tradicionalan
nain pomou var, koje vae u celom okruujuem opsegu vidljivosti funkcije u kojem
su deklarisane, let deklaracije se dodaju u opseg vidljivosti svog bloka, ali se ne inicijali-
zuju sve do mesta gde se pojavljuju u bloku.
Pristupanje promenljivoj koja je deklarisana pomou let pre njene let .. deklaraci-
je/inicijalizacije prouzrokuje greku, dok je za var deklaracije taj redosled nevaan (osim
u pogledu stila).
Razmotrite sledee:
{
console.log( a ); // undefined
console.log( b ); // ReferenceError!
var a;
let b;
}
648|Poglavlje 27Sintaksa
Ta greka ReferenceError zbog preranog pristupanja promenljivoj koja je de-
klarisana pomou let tehniki se zove TDZ (Temporal Dead Zone privreme-
na mrtva zona) greka pristupate promenljivoj koja je deklarisana ali jo nije
inicijalizovana. To nije jedini sluaj kada viamo TDZ greke one se u ES6 po-
javljuju na vie mesta. Osim toga, imajte u vidu da inicijalizovana ne znai
eksplicitno dodeljivanje vrednosti u kodu, poto je let b; potpuno ispravna sintaksa. Budui
da se za promenljivu kojoj u trenutku deklarisanja nije dodeljena nikakva vrednost podrazu-
meva da joj je dodeljena vrednost undefined, iskaz let b; isto je to i let b = unde fined;.
Bez obzira na to da li je inicijalizujete eksplicitno ili implicitno, promenljivoj b ne moete pri-
stupati dok se ne izvri iskaz let b.
// ..
let b;
}
Poto promenljiva a nije deklarisana, upotreba operatora typeof jedini je bezbedan
nain da proverimo postoji li ona ili ne. Ali, izraz typeof b prouzrokuje TDZ greku zato
to duboko nie u kodu sluajno imamo deklaraciju let b. Uh.
Sada bi trebalo da bude jasnije zbog ega insistiram da se sve let deklaracije nalaze
na poetku svojih opsega vidljivosti. Tako se potpuno izbegavaju nenamerne greke zbog
preranog pristupanja promenljivoj. Osim toga, tako postaje eksplicitnije kada pogleda-
te poetak bloka, svakog bloka koje promenljive on sadri.
Vai blokovi (iskazi if, petlje while itd.) ne moraju da dele svoje izvorno ponaanje s
ponaanjem u vezi sa opsegom vidljivosti.
Ta vaa eksplicitnost, koju ete samo morati da disciplinovano odravate, na dui rok
e vas potedeti mnogih glavobolja.
funcs[3](); // 3
Izraz let i u zaglavlju petlje for deklarie promenljivu i ne samo za petlju for, nego
ponovo deklarie novu promenljivu i u svakoj iteraciji petlje. To znai da ograde koje se
formiraju unutar jedne iteracije petlje ograuju te promenljive po iteraciji, kao to biste
i oekivali.
Ako isprobate isti primer, ali s deklaracijom var i u zaglavlju petlje for, rezultat e biti
5 umesto 3, zato to bi u spoljanjem opsegu koji funkcija ograuje postojala samo jed-
na promenljiva i, umesto nove promenljive i u svakoj iteraciji koju bi funkcija ogradila.
Isto moete postii i u neznatno opirnijem obliku:
var funcs = [];
funcs[3](); // 3
U ovom sluaju, izriito deklariemo novu promenljivu j u svakoj deklaraciji, a nakon
toga ograda deluje na isti nain. Drae mi je prvo reenje; zbog dodatne mogunosti koju
ono prua radije se opredeljujem za oblik for (let .. ) ... Moe se opravdano zame-
riti da je to malo implicitniji oblik, ali je za moj ukus ipak dovoljno eksplicitan i koristan.
Deklaracija pomou let ponaa se na isti nain i u petljama for..in i for..of (videti
odeljak Petlja for..of na strani 693).
Deklarisanje konstanti
Postoji jo jedna deklaracija iji opseg vaenja je blok: to je deklaracija pomou rezervi-
sane rei const, ime se formiraju konstante.
650|Poglavlje 27Sintaksa
ta je tano konstanta? To je promenljiva ija se vrednost nakon inicijalizovanja moe
samo itati. Razmotrite sledee:
{
const a = 2;
console.log( a ); // 2
a = 3; // greka TypeError!
}
Nakon inicijalizovanja vrednosti promenljive, u trenutku deklarisanja, vie nije dozvo-
ljeno menjati tu vrednost. Deklaracija const mora sadrati i eksplicitnu operaciju inicija-
lizovanja vrednosti promenljive. Ako elite da vrednost konstante bude undefined, mora-
te deklarisati const a = undefined.
Konstante ni po emu ne ograniavaju samu vrednost, nego samo dodeljivanje vred-
nosti konstanti. Drugim reima, sama vrednost nije zbog deklaracije const postala ni za-
mrznuta, ni nepromenljiva, nego to vai samo za operaciju dodeljivanja vrednosti. Ako
je to neka sloena vrednost, kao to je objekat ili niz, sadraj te vrednosti se i dalje moe
menjati:
{
const a = [1,2,3];
a.push( 4 );
console.log( a ); // [1,2,3,4]
Dodeljivanje objekta ili niza kao vrednost konstante znai da sakuplja smea
nee moi da pokupi tu vrednost sve dok leksiki opseg vidljivosti te konstante
ne nestane, zato to se nikad ne moe izbrisati referenca na tu vrednost. To moe
biti poeljno, ali vodite rauna ako vam to nije bila namera!
U sutini, deklaracija pomou const sada samo namee ono to smo godinama ugra-
ivali u kd kao stilski oblik, gde smo ime promenljive deklarisali velikim slovima i do-
deljivali joj neku literalnu vrednost za koju smo vodili rauna da je nakon toga nikad ne
menjamo. Nema ogranienja za promenljive deklarisane pomou var, ali ima za promen-
ljive deklarisane pomou const, to moe da vam pomogne da otkrijete nenamerne iz-
mene vrednosti.
Rezervisana re const moe se upotrebiti za deklarisanje promenljivih u petljama for,
for..in i for..of (videti odeljak Petlja for..of na strani 693). Meutim, svaki pokuaj
dodeljivanja nove vrednosti, kao to je u tipinoj odredbi i++ petlje for, prouzrokovae
greku.
function foo() {
// ..
}
}
foo(); // ReferenceError
Funkcija foo() je deklarisana unutar bloka { .. } i za ES6 njen opseg vidljivosti je taj
blok. Dakle, ona nije vidljiva izvan tog bloka. Ali obratite panju i na to da je deklaracija
funkcije podignuta na poetak bloka, za razliku od let deklaracija, koje uvode ve ra-
nije pomenutu zamku TDZ greke.
652|Poglavlje 27Sintaksa
Deklarisanje funkcija iji je opseg vidljivosti blok moe biti problem ako ste navi-
kli da piete kd kao to je sledei i oekujete ponaanje kao ranije, kad opseg vidljivo-
sti nije bio blok:
if (something) {
function foo() {
console.log( 1 );
}
}
else {
function foo() {
console.log( 2 );
}
}
foo(); // ??
U okruenjima starijim od ES6, funkcija foo() bi uvek ispisala 2 bez obzira na vred-
nost something, zato to su se obe deklaracije funkcije izvlaile iz svojih blokova i uvek bi
vaila samo poslednja deklaracija.
U ES6, poslednji red izaziva greku ReferenceError.
console.log( b ); // [1,2,3,4,5]