2.8 For...in
Výuka
Co je for...in?
for...in iteruje přes klíče (vlastnosti) objektu. Na rozdíl od for...of, který iteruje přes hodnoty.
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
console.log(key); // "a", "b", "c" - KLÍČE
}
Kdy použít for...in?
✅ Vhodné pro:
- Iteraci přes vlastnosti objektu
- Zjištění, jaké klíče objekt má
- Dynamické zpracování objektů
❌ NEPOUŽÍVEJ pro:
- Pole (vrací indexy jako stringy, může zahrnout zděděné vlastnosti)
- Když potřebuješ garantované pořadí
for...in vs for...of - Zásadní rozdíl!
const arr = ["a", "b", "c"];
// for...in - KLÍČE (indexy)
for (const key in arr) {
console.log(key); // "0", "1", "2" (stringy!)
}
// for...of - HODNOTY
for (const value of arr) {
console.log(value); // "a", "b", "c"
}
JavaScript
// Základní for...in na objektu
const user = {
name: "Jan",
age: 25,
city: "Praha"
};
for (const key in user) {
console.log(`${key}: ${user[key]}`);
}
// "name: Jan", "age: 25", "city: Praha"
// Problém: zděděné vlastnosti
const parent = { inherited: true };
const child = Object.create(parent);
child.own = "vlastní";
for (const key in child) {
console.log(key); // "own" A "inherited" - obě!
}
// Řešení: hasOwnProperty
for (const key in child) {
if (child.hasOwnProperty(key)) {
console.log(key); // Jen "own"
}
}
// Moderní alternativa: Object.hasOwn (ES2022)
for (const key in child) {
if (Object.hasOwn(child, key)) {
console.log(key);
}
}
// POZOR na pole!
const fruits = ["jablko", "banán"];
fruits.customProp = "extra"; // Přidaná vlastnost
for (const key in fruits) {
console.log(key); // "0", "1", "customProp" - i extra vlastnost!
}
// Pro pole VŽDY použij for...of
for (const fruit of fruits) {
console.log(fruit); // "jablko", "banán" - jen prvky
}
// Dynamické zpracování objektu
const config = {
debug: true,
apiUrl: "https://api.example.com",
timeout: 5000
};
for (const key in config) {
const value = config[key];
console.log(`Nastavení: ${key} = ${value}`);
}
// Kopírování objektu (shallow)
const original = { a: 1, b: 2 };
const copy = {};
for (const key in original) {
copy[key] = original[key];
}
// Lepší způsob kopírování
const betterCopy = { ...original };
const betterCopy2 = Object.assign({}, original);
// Porovnání dvou objektů
function shallowEqual(obj1, obj2) {
for (const key in obj1) {
if (obj1[key] !== obj2[key]) {
return false;
}
}
for (const key in obj2) {
if (!(key in obj1)) {
return false;
}
}
return true;
}
TypeScript
// Základní for...in s typy
const user = {
name: "Jan",
age: 25,
city: "Praha"
};
for (const key in user) {
// key je string, ne keyof typeof user!
console.log(key);
}
// Problém: TypeScript neví přesný typ klíče
for (const key in user) {
// ❌ Error: Element implicitly has 'any' type
// console.log(user[key]);
// ✅ Řešení: type assertion
console.log(user[key as keyof typeof user]);
}
// Lepší: Object.entries nebo Object.keys
for (const [key, value] of Object.entries(user)) {
// key: string, value: string | number
console.log(`${key}: ${value}`);
}
// Type-safe iterace s keyof
type User = {
name: string;
age: number;
email: string;
};
const userData: User = {
name: "Jan",
age: 25,
email: "jan@email.cz"
};
// Pomocná funkce pro type-safe for...in
function forEachKey<T extends object>(
obj: T,
callback: (key: keyof T, value: T[keyof T]) => void
): void {
for (const key in obj) {
if (Object.hasOwn(obj, key)) {
callback(key as keyof T, obj[key as keyof T]);
}
}
}
forEachKey(userData, (key, value) => {
console.log(`${key}: ${value}`);
});
// Record typ
const translations: Record<string, string> = {
hello: "ahoj",
goodbye: "nashledanou"
};
for (const key in translations) {
// key: string, translations[key]: string
console.log(`${key} = ${translations[key]}`);
}
// Index signature
interface Config {
[key: string]: string | number | boolean;
}
const config: Config = {
debug: true,
timeout: 5000
};
for (const key in config) {
const value = config[key]; // string | number | boolean
console.log(`${key}: ${value}`);
}
Rozdíl JS vs TS
| JavaScript | TypeScript |
|---|---|
key je vždy string |
key je string, ale ne automaticky keyof |
obj[key] bez problémů |
obj[key] může vyžadovat assertion |
| Žádná kontrola | TS varuje před potenciálně chybným přístupem |
Proč TypeScript "zlobí" s for...in?
const user = { name: "Jan", age: 25 };
for (const key in user) {
// TypeScript neví, že key je "name" | "age"
// Protože objekt může mít i další vlastnosti za runtime
user[key]; // ❌ Error
}
// Řešení 1: Type assertion
user[key as keyof typeof user];
// Řešení 2: Object.keys s assertion
(Object.keys(user) as (keyof typeof user)[]).forEach(key => {
console.log(user[key]); // ✅ OK
});
// Řešení 3: Object.entries
Object.entries(user).forEach(([key, value]) => {
console.log(key, value); // ✅ OK
});
Tip
💡 Pro pole NIKDY nepoužívej for...in:
const arr = ["a", "b", "c"];
// ❌ ŠPATNĚ
for (const key in arr) {
console.log(key); // "0", "1", "2" (stringy!)
}
// ✅ SPRÁVNĚ
for (const value of arr) {
console.log(value); // "a", "b", "c"
}
// ✅ SPRÁVNĚ - když potřebuješ index
arr.forEach((value, index) => {
console.log(index, value);
});
💡 Preferuj Object.keys/values/entries:
const obj = { a: 1, b: 2 };
// Modernější a čitelnější
Object.keys(obj); // ["a", "b"]
Object.values(obj); // [1, 2]
Object.entries(obj); // [["a", 1], ["b", 2]]
// Použij s for...of
for (const [key, value] of Object.entries(obj)) {
console.log(key, value);
}
💡 Filtruj zděděné vlastnosti:
for (const key in obj) {
if (Object.hasOwn(obj, key)) { // ES2022+
// nebo: obj.hasOwnProperty(key)
console.log(key);
}
}
Kvíz
Které výroky jsou pravdivé?
❌ - for...in iteruje přes KLÍČE, ne hodnoty (pro hodnoty je for...of)
✅ - Indexy jsou vráceny jako stringy: "0", "1", "2"
✅ - for...in zahrnuje i zděděné vlastnosti (proto používáme hasOwnProperty)
❌ - Pro pole se doporučuje for...of nebo array metody, ne for...in
🎯 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
- 2.1 If / else
- 2.2 Else if
- 2.3 Ternární operátor
- 2.4 Switch
- 2.5 For cyklus
- 2.6 While a do-while
- 2.7 For...of
- 2.8 For...in
- 2.9 Break a continue
- 2.10 Truthy a Falsy hodnoty
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ě