Informace v tomto Älánku jsou užiteÄné k tomu, abyste porozumÄli starým skriptům.
Nenà to způsob, jak psát nový kód.
V úplnÄ prvnà kapitole o promÄnných jsme zmÃnili tÅi způsoby deklarace promÄnných:
letconstvar
Deklarace var je podobná let. Ve vÄtÅ¡inÄ pÅÃpadů můžeme nahradit let za var nebo naopak a oÄekávat, že vÅ¡e bude fungovat:
var zpráva = "Ahoj";
alert(zpráva); // Ahoj
VnitÅnÄ je vÅ¡ak var velmi odliÅ¡ná potvůrka, která pocházà z dÅÃvÄjÅ¡Ãch Äasů. V modernÃch skriptech se obvykle nepoužÃvá, ale ve starých stále ÄÃhá.
Pokud neplánujete se s takovými skripty setkat, můžete tuto kapitolu pÅeskoÄit nebo odložit na pozdÄji.
Naproti tomu, když pÅevádÃte staré skripty z var na let, je důležité porozumÄt rozdÃlům, abyste se vyhnuli podivným chybám.
âvarâ nemá blokovou platnost
PromÄnné deklarované pomocà var majà rozsah platnosti buÄ funkÄnÃ, nebo globálnÃ. Jsou viditelné i skrz bloky.
NapÅÃklad:
if (true) {
var test = true; // použijeme âvarâ namÃsto âletâ
}
alert(test); // true, promÄnná existuje i za if
Protože var ignoruje kódové bloky, vytvoÅili jsme globálnà promÄnnou test.
Kdybychom použili let test namÃsto var test, pak by tato promÄnná byla viditelná jen uvnitÅ if:
if (true) {
let test = true; // použijeme âletâ
}
alert(test); // ReferenceError: test nenà definován
Totéž platà pro cykly: var nemůže být lokálnà v bloku nebo ve smyÄce:
for (var i = 0; i < 10; i++) {
var jedna = 1;
// ...
}
alert(i); // 10, âiâ je viditelná i za cyklem, je to globálnà promÄnná
alert(jedna); // 1, âjednaâ je viditelná i za cyklem, je to globálnà promÄnná
NacházÃ-li se kódový blok uvnitÅ funkce, pak var deklaruje promÄnnou na úrovni funkce:
function ÅekniAhoj() {
if (true) {
var vÄta = "Ahoj";
}
alert(vÄta); // funguje
}
ÅekniAhoj();
alert(vÄta); // ReferenceError: vÄta nenà definována
Jak vidÃme, var se probije skrz if, for a jiné kódové bloky. Je to proto, že pÅed dlouhou dobou bloky v JavaScriptu nemÄly lexikálnà prostÅedà a var je toho pozůstatkem.
âvarâ toleruje opakované deklarace
Jestliže deklarujeme stejnou promÄnnou pomocà let ve stejné oblasti dvakrát, nastane chyba:
let uživatel;
let uživatel; // SyntaxError: 'uživatel' již byl deklarován
Pomocà var můžeme znovu deklarovat promÄnnou, kolikrát chceme. Použijeme-li var s již deklarovanou promÄnnou, bude ignorováno:
var uživatel = "Petr";
var uživatel = "Jan"; // tento âvarâ neudÄlá nic (promÄnná je již deklarována)
// ...nevyvolá chybu
alert(uživatel); // Jan
Pomocà âvarâ můžeme promÄnné deklarovat až po jejich použitÃ
Deklarace var se zpracovávajÃ, když se funkce spustà (nebo když se spustà skript, jsou-li globálnÃ).
Jinými slovy, promÄnné deklarované pomocà var jsou definovány od zaÄátku funkce bez ohledu na to, kde se jejich definice nacházà (za pÅedpokladu, že definice nenà uvnitÅ vnoÅené funkce).
Takže tento kód:
function ÅekniAhoj() {
vÄta = "Ahoj";
alert(vÄta);
var vÄta;
}
ÅekniAhoj();
â¦je technicky stejný jako tento (pÅesuneme var vÄta nahoru):
function ÅekniAhoj() {
var vÄta;
vÄta = "Ahoj";
alert(vÄta);
}
ÅekniAhoj();
â¦Nebo i jako tento (pamatujte, že kódové bloky jsou ignorovány):
function ÅekniAhoj() {
vÄta = "Ahoj"; // (*)
if (false) {
var vÄta;
}
alert(vÄta);
}
ÅekniAhoj();
Takovému chovánà se nÄkdy ÅÃká âstoupánÃâ (anglicky âhoistingâ nebo âraisingâ), jelikož každý var âvystoupáâ (âhoistâ, âraiseâ) až k vrcholu funkce.
V uvedeném pÅÃkladu se vÄtev if (false) nikdy nespustÃ, ale na tom nezáležÃ. PÅÃkaz var uvnitÅ se zpracuje na zaÄátku funkce, takže v okamžiku provedenà Åádku (*) promÄnná existuje.
Deklarace stoupajÃ, ale pÅiÅazenà ne.
Nejlépe to uvidÃme na pÅÃkladu:
function ÅekniAhoj() {
alert(vÄta);
var vÄta = "Ahoj";
}
ÅekniAhoj();
Åádek var vÄta = "Ahoj" má v sobÄ dvÄ akce:
- Deklaraci promÄnné
var. - PÅiÅazenà promÄnné
=.
Deklarace se vykonává na zaÄátku spuÅ¡tÄnà funkce (âstoupánÃâ), ale pÅiÅazenà se provede vždy na mÃstÄ, na nÄmž se objevilo. Kód tedy funguje v zásadÄ následovnÄ:
function ÅekniAhoj() {
var vÄta; // deklarace se provede na zaÄátku...
alert(vÄta); // undefined
vÄta = "Ahoj"; // ...pÅiÅazenà - když se bÄh dostane k nÄmu.
}
ÅekniAhoj();
Protože vÅ¡echny deklarace var se zpracovávajà na zaÄátku funkce, můžeme je uvádÄt kdekoli. Ale promÄnné jsou až do pÅiÅazenà nedefinované.
V obou uvedených pÅÃkladech se alert spustà bez chyby, protože promÄnná vÄta existuje. Ale jeÅ¡tÄ jà nenà pÅiÅazena hodnota, takže se zobrazà undefined.
IIFE
V minulosti, kdy bylo jenom var a neexistovala viditelnost na úrovni bloku, programátoÅi vymysleli způsob, jak ji emulovat. To, co vynalezli, bylo nazváno âokamžitÄ volané funkÄnà výrazyâ (âimmediately-invoked function expressionsâ), zkrácenÄ IIFE.
Nenà to nic, co bychom mÄli použÃvat v souÄasnosti, ale ve starých skriptech je stále můžete najÃt.
IIFE vypadá následovnÄ:
(function() {
var zpráva = "Ahoj";
alert(zpráva); // Ahoj
})();
Zde se vytvoÅà a okamžitÄ zavolá funkÄnà výraz. Kód se tedy okamžitÄ spustà a má své vlastnà soukromé promÄnné.
FunkÄnà výraz je uzavÅen do závorek (function {...}), protože když motor JavaScriptu narazà v hlavnÃm kódu na âfunctionâ, chápe to jako zaÄátek deklarace funkce. AvÅ¡ak deklarace funkce musà obsahovat název, takže tento kód vyvolá chybu:
// Snažà se deklarovat a okamžitÄ zavolat funkci
function() { // <-- SyntaxError: Deklarace funkce vyžaduje název funkce
var zpráva = "Ahoj";
alert(zpráva); // Ahoj
}();
I kdybychom si Åekli: âdobÅe, tak pÅidáme názevâ, nebude to fungovat, protože JavaScript neumožÅuje, aby byla deklarace funkce okamžitÄ volána:
// závorky nÞe způsobà syntaktickou chybu
function jdi() {
}(); // <-- deklaraci funkce nemůžeme okamžitÄ volat
Závorky kolem funkce jsou tedy trik, jak ukázat JavaScriptu, že funkce je vytvoÅena v kontextu jiného výrazu, a proto je to funkÄnà výraz: nemusà mÃt název a může být okamžitÄ zavolán.
KromÄ závorek existujà i jiné způsoby, jak oznámit JavaScriptu, že máme na mysli funkÄnà výraz:
// Způsoby vytvoÅenà IIFE
(function() {
alert("Závorky okolo funkce");
})();
(function() {
alert("Závorky okolo toho všeho");
}());
!function() {
alert("Bitový operátor NOT zahajuje výraz");
}();
+function() {
alert("Unárnà plus zahajuje výraz");
}();
Ve vÅ¡ech uvedených pÅÃpadech deklarujeme funkÄnà výraz a okamžitÄ jej zavoláme. Znovu opakujeme, že v dneÅ¡nà dobÄ nenà důvod takový kód psát.
ShrnutÃ
Mezi var a let/const existujà dva hlavnà rozdÃly:
- PromÄnné deklarované pomocÃ
varnemajà blokovou platnost a oblast jejich viditelnosti je celá aktuálnà funkce. Jsou-li deklarovány mimo funkci, jsou globálnÃ. - Deklarace
varse zpracovávajà na zaÄátku funkce (globálnà deklarace na zaÄátku skriptu).
Existuje jeÅ¡tÄ jeden velmi drobný rozdÃl vztahujÃcà se ke globálnÃmu objektu, který probereme v pÅÃÅ¡tà kapitole.
Kvůli tÄmto rozdÃlům je var ve vÄtÅ¡inÄ pÅÃpadů horšà než let. PromÄnné na úrovni bloku jsou vynikajÃcà vÄc. To je důvod, proÄ bylo do standardu již pÅed dlouhou dobou zavedeno let a nynà je hlavnÃm způsobem (spolu s const), jak deklarovat promÄnné.
KomentáÅe
<code>, pro nÄkolik Åádků je obalte znaÄkou<pre>, pro vÃce než 10 Åádků vložte odkaz na pÃskoviÅ¡tÄ (plnkr, jsbin, codepenâ¦)