03.10 Řetězec Scope
Výuka
Proč řetězec scope?
V minulých lekcích jsi viděl, že scope určuje, kde je proměnná viditelná, a že JavaScript hledá proměnné "zevnitř ven". Ale jak přesně probíhá tohle hledání?
const level1 = "Globální";
function outer() {
const level2 = "Outer";
function inner() {
const level3 = "Inner";
console.log(level1); // Jak JavaScript najde level1?
}
inner();
}
outer(); // → "Globální"
Scope chain (řetězec scope) je cesta, kterou JavaScript sleduje při hledání proměnné. Je to jako řetěz spojující všechny vnořené scope dohromady.
Proč je to užitečné?
- Předvídatelné chování - víš přesně, kde JavaScript bude hledat
- Organizace kódu - vnitřní funkce vidí kontext vnějších funkcí
- Izolace - každý scope má vlastní proměnné, ale může vidět "nahoru"
Představ si to jako: Panenky matryošky - když hledáš něco v nejmenší panenče, podíváš se dovnitř. Pokud to tam není, otevřeš větší panenku, pak ještě větší, až najdeš, co hledáš.
Jak to funguje?
Scope chain = posloupnost scope, kde JavaScript hledá proměnnou:
1. JavaScript začne hledat v AKTUÁLNÍM scope
2. Pokud nenajde, podívá se do NADŘAZENÉHO scope
3. Pokračuje VEN až ke GLOBÁLNÍMU scope
4. Pokud nenajde ANI TAM, vyhodí ReferenceError
5. Jakmile najde první shodu, PŘESTANE hledat
Důležité pravidla:
- Hledání jde jen jedním směrem - zevnitř ven (nikdy dovnitř!)
- Hledání se zastaví u první shody - i kdyby bylo víc shod výš
- Řetězec je statický - určený při psaní kódu, ne při spuštění
Klíčové koncepty
- Scope chain - posloupnost vnořených scope, kterou JavaScript prochází při hledání
- Lookup (hledání) - proces hledání proměnné od aktuálního scope ven
- Směr hledání - vždycky zevnitř ven, nikdy dovnitř nebo napříč
- První shoda vyhrává - jakmile najde proměnnou, přestane hledat
- Shadowing - když vnitřní proměnná "zakryje" vnější se stejným jménem
JavaScript
Příklad 1: Základní scope chain
const a = "úroveň 1 (globální)";
function level2() {
const b = "úroveň 2";
function level3() {
const c = "úroveň 3";
console.log(c); // Krok 1: Hledá v level3 → NAŠEL ✅
console.log(b); // Krok 1: Hledá v level3 → nenašel
// Krok 2: Hledá v level2 → NAŠEL ✅
console.log(a); // Krok 1: Hledá v level3 → nenašel
// Krok 2: Hledá v level2 → nenašel
// Krok 3: Hledá v global → NAŠEL ✅
}
level3();
}
level2();
// → úroveň 3
// → úroveň 2
// → úroveň 1 (globální)
Co se stalo?
- JavaScript vždycky začne hledat v aktuálním scope (level3)
- Pokud nenajde, pokračuje nahoru řetězem (level2 → global)
- Jakmile najde první shodu, přestane hledat
- To je scope chain - cesta zevnitř ven!
Příklad 2: Shadowing - zastínění proměnné
const name = "Alice (globální)";
function outer() {
const name = "Bob (outer)"; // Zakryje globální name
function inner() {
const name = "Charlie (inner)"; // Zakryje outer name
console.log(name); // Která name?
}
inner();
console.log(name); // Která name?
}
outer();
console.log(name); // Která name?
// → Charlie (inner)
// → Bob (outer)
// → Alice (globální)
Co se stalo?
- Každý scope má vlastní proměnnou
name - JavaScript použije nejbližší shodu v scope chain
- Funkce
innervidí jen svojíname(Charlie) - ostatní jsou zakryté (shadowed) - Funkce
outervidí jen svojíname(Bob) - Globální scope vidí svojí
name(Alice) - Shadowing = vnitřní proměnná zakryje vnější se stejným jménem
Příklad 3: Hledání se zastaví u první shody
const x = 1;
function level1() {
const x = 2;
function level2() {
const x = 3;
function level3() {
console.log(x); // Najde x = 3 v level2 a PŘESTANE hledat
}
level3();
}
level2();
}
level1();
// → 3
Co se stalo?
- JavaScript hledá
xvlevel3→ nenajde - Hledá v
level2→ našel! (x = 3) - Přestane hledat - nepokračuje k level1 nebo globálnímu scope
- I když existuje
xs hodnotou 2 a 1, JavaScript je nikdy nevidí
Příklad 4: Scope chain jde jen ven, ne dovnitř
function outer() {
const outerVar = "Jsem v outer";
function inner() {
const innerVar = "Jsem v inner";
console.log(outerVar); // ✅ Vidí ven do outer
}
inner();
console.log(innerVar); // ❌ Error: innerVar is not defined
}
outer();
Co se stalo?
- Funkce
innervidí ven doouter- scope chain jde nahoru ✅ - Funkce
outernevidí dovnitř doinner- scope chain NEJDE dolů ❌ - Scope chain je jednosměrný - jen zevnitř ven!
Příklad 5: Každé volání funkce má vlastní scope
function makeCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter1 = makeCounter();
const counter2 = makeCounter();
console.log(counter1()); // → 1
console.log(counter1()); // → 2
console.log(counter2()); // → 1 (vlastní count!)
console.log(counter1()); // → 3
Co se stalo?
- Každé volání
makeCounter()vytvoří nový scope s vlastnícount counter1acounter2mají vlastní scope chain - každý vidí svoucount- To je closure - funkce si pamatuje scope, ve kterém byla vytvořená
- O closures více v lekci 14!
Příklad 6: Vizualizace scope chain
const global = "G"; // 🔴 Globální scope
function outer() { // 🔵 Outer scope
const outerVar = "O";
function middle() { // 🟢 Middle scope
const middleVar = "M";
function inner() { // 🟡 Inner scope
const innerVar = "I";
// Scope chain pro inner:
// 🟡 inner → 🟢 middle → 🔵 outer → 🔴 global
console.log(innerVar); // 🟡 Najde v inner
console.log(middleVar); // 🟢 Najde v middle
console.log(outerVar); // 🔵 Najde v outer
console.log(global); // 🔴 Najde v global
}
inner();
}
middle();
}
outer();
Co se stalo?
- Scope chain je posloupnost: inner → middle → outer → global
- JavaScript hledá postupně každý scope, dokud nenajde proměnnou
- Každý scope vidí všechny nadřazené scope, ale ne podřazené
TypeScript
TypeScript používá stejný scope chain jako JavaScript. Scope chain funguje identicky!
const message: string = "Globální";
function outer(): void {
const message: string = "Outer";
function inner(): void {
const message: string = "Inner";
console.log(message); // Scope chain: inner → outer → global
}
inner(); // → "Inner"
}
outer();
TypeScript kontroluje scope chain při kompilaci:
const x: number = 10;
function test(): void {
const y: number = 20;
function nested(): void {
console.log(x); // ✅ TypeScript ví, že x je v scope chain
console.log(y); // ✅ TypeScript ví, že y je v scope chain
console.log(z); // ❌ Compile error: Cannot find name 'z'
}
nested();
}
test();
TypeScript přidává:
- ✅ Kontrola dostupnosti - upozorní, pokud proměnná není v scope chain
- ✅ Lepší IntelliSense - editor ti ukáže všechny dostupné proměnné v scope chain
- ✅ Typová bezpečnost - kontroluje typy napříč celým scope chain
Rozdíl JS vs TS
JavaScript:
const name = "Alice";
function test() {
console.log(name); // ✅ Funguje - name je v scope chain
console.log(age); // 💥 Runtime error: age is not defined
}
test();
TypeScript:
const name: string = "Alice";
function test(): void {
console.log(name); // ✅ Funguje - name je v scope chain
console.log(age); // ❌ Compile error: Cannot find name 'age'
}
test();
Rozdíl:
- JavaScript najde chybu až při spuštění - když JavaScript prohledá celý scope chain a nenajde
age - TypeScript najde chybu při psaní - analyzuje scope chain bez spuštění kódu
Tip
💡 Shadowing může být matoucí - používej různé názvy:
// ⚠️ Matoucí - stejný název všude
const data = "globální";
function process() {
const data = "lokální"; // Zakryje globální
function transform() {
const data = "vnořená"; // Zakryje lokální
console.log(data); // Která data?
}
transform();
}
// ✅ Lepší - jasné názvy
const globalData = "globální";
function process() {
const processData = "lokální";
function transform() {
const transformedData = "vnořená";
console.log(transformedData); // Jasné!
}
transform();
}
💡 Deklaruj proměnné ve správném scope:
// ❌ Špatně - zbytečně globální
let result;
function calculate() {
result = 42; // Používá globální proměnnou
return result;
}
console.log(calculate());
// ✅ Dobře - lokální scope
function calculate() {
const result = 42; // Lokální proměnná
return result;
}
console.log(calculate());
💡 Chápeš scope chain? Zkus předpovědět výsledek:
const x = "A";
function first() {
const x = "B";
function second() {
console.log(x); // Co vypíše?
}
second();
}
first();
// → "B" (scope chain: second → first → global, najde v first)
Kvíz
Co se stane, když JavaScript hledá proměnnou v scope chain?
const value = 1;
function outer() {
const value = 2;
function inner() {
console.log(value);
}
inner();
}
outer();
❌ - Globální value je v scope chain, ale není nejbližší
✅ - JavaScript najde value = 2 v outer jako první shodu a přestane hledat
❌ - Shadowing neznamená undefined, jen že vnitřní proměnná má přednost
❌ - Shadowing je legální a běžná součást scope chain
🎯 Závěrečný projekt
Po dokončení všech 8 dílů vytvoříte jednoduchou Todо aplikaci v čistém JavaScriptu. Naučíte se, jak aplikovat vše, co jste se naučili, na reálný projekt.
Zobrazit podrobnosti projektu →Informace o seriálu
Obtížnost
Délka
Cca 480 minut
Počet videí
8 videí + projekty
Certifikát
Po dokončení obdržíte certifikát
Lekce v této sekci
- 03.01 Deklarace funkce
- 03.02 Function Expression
- 03.03 Arrow Functions
- 03.04 Parametry a argumenty
- 03.05 Return hodnoty
- 03.06 Výchozí parametry
- 03.07 Rest parametry
- 03.08 Co je Scope
- 03.09 Lexikální Scope
- 03.10 Řetězec Scope
- 03.11 Globální Scope
- 03.12 Životní Cyklus Proměnných
- 03.13 Omezení Scope
- 03.14 Použití Closures
- 03.15 Callback funkce
- 03.16 Higher-order Functions
- 03.17 IIFE
- 03.18 Void funkce
- 03.19 Rekurze
Struktura lekcí (souborový strom)
- 1.1 Úvod do JavaScriptu a TypeScriptu
- 1.2 Nastavení prostředí
- 1.3 První program
- 1.4 Proměnné: var, let, const
- 1.5 Datové typy - přehled
- 1.6 String (řetězce)
- 1.7 Number (čísla)
- 1.8 Boolean (pravda/nepravda)
- 1.9 Null a Undefined
- 1.10 Type Inference vs Annotations
- 1.11 Aritmetické operátory
- 1.12 Porovnávací operátory
- 1.13 Logické operátory
- 1.14 Komentáře
- 1.15 Console metody
- 03.01 Deklarace funkce
- 03.02 Function Expression
- 03.03 Arrow Functions
- 03.04 Parametry a argumenty
- 03.05 Return hodnoty
- 03.06 Výchozí parametry
- 03.07 Rest parametry
- 03.08 Co je Scope
- 03.09 Lexikální Scope
- 03.10 Řetězec Scope
- 03.11 Globální Scope
- 03.12 Životní Cyklus Proměnných
- 03.13 Omezení Scope
- 03.14 Použití Closures
- 03.15 Callback funkce
- 03.16 Higher-order Functions
- 03.17 IIFE
- 03.18 Void funkce
- 03.19 Rekurze
- v přípravě
- v přípravě
- v přípravě
- v přípravě
- 01 — Co je Next.js
- 02 — Vytvoření projektu
- 03 — Struktura projektu (app/)
- 04 — Page komponenty (page.js / page.tsx)
- 05 — Layout komponenty (layout.js / layout.tsx)
- 06 — File-based routing
- 07 — Dynamické routy ([id]/page.js)
- 08 — Link komponenta (navigace)
- 09 — Image komponenta (next/image)
- 10 — Metadata (title, description, Open Graph)
- 11 — Loading UI (loading.js / loading.tsx)
- 12 — Error handling (error.js / error.tsx)
- 13 — Not Found (not-found.js / not-found.tsx)
- v přípravě
- v přípravě
- v přípravě