Appearance
Kapitel 2: Variablen-Deklaration - let und const
2.1 Probleme mit var (Hoisting, doppelte Deklaration, Scope-Chaos)
❌ Problem 1: Variablen-Hoisting (Anheben)
In JavaScript werden var Variablen hochgezogen (hoisting) zum Anfang des Scopes.
javascript
// Seltsames Verhalten mit var
console.log(name); // undefined (kein Fehler!)
var name = "Max";
// JS-Engine interpretiert es so:
var name; // Deklaration wird hochgezogen
console.log(name); // undefined
name = "Max"; // Zuweisung bleibt am ursprünglichen OrtProblem: Du kannst eine Variable verwenden, bevor sie deklariert wurde (ergibt undefined, keine Fehlermeldung).
❌ Problem 2: Doppelte Deklaration erlaubt
Mit var kannst du dieselbe Variable mehrfach deklarieren, ohne dass ein Fehler auftritt.
javascript
var count = 1;
var count = 2; // Kein Fehler!
console.log(count); // 2
// In großen Projekten leicht passiert:
var total = 100;
// ... 100 Zeilen Code ...
var total = 200; // Überschreibt die vorherige Variable!Problem: Fehler durch versehentliches Überschreiben von Variablen.
❌ Problem 3: Kein Block-Scope
var hat nur Funktions-Scope, kein Block-Scope.
javascript
if (true) {
var message = "Hallo";
}
console.log(message); // "Hallo" (zugreifbar außerhalb des Blocks!)
for (var i = 0; i < 5; i++) {
var text = "ES6";
}
console.log(i); // 5 (zugreifbar!)
console.log(text); // "ES6" (zugreifbar!)Problem: Variablen "lecken" aus Blöcken heraus.
❌ Problem 4: Loop-Problem (Klassiker!)
javascript
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i); // Immer 5! (nicht 0, 1, 2, 3, 4)
}, 100);
}Grund: Alle 5 setTimeout-Callbacks teilen sich dieselbe i-Variable, die am Ende der Schleife 5 ist.
2.2 let - Variable Deklaration (Block-Scope, keine doppelte Deklaration)
✅ Vorteil 1: Block-Scope
Mit let ist eine Variable nur innerhalb ihres Blocks { } zugreifbar.
javascript
if (true) {
let message = "Hallo";
console.log(message); // "Hallo" ✅
}
console.log(message); // ❌ ReferenceError: message is not defined
{
let x = 10;
console.log(x); // 10 ✅
}
console.log(x); // ❌ ReferenceError✅ Vorteil 2: Keine doppelte Deklaration
javascript
let count = 1;
let count = 2; // ❌ SyntaxError: Identifier 'count' has already been declared✅ Vorteil 3: Kein Hoisting (Temporal Dead Zone)
javascript
console.log(name); // ❌ ReferenceError (nicht undefined!)
let name = "Max";
// "Temporal Dead Zone" (TDZ):
// Auf die Variable kann nicht zugegriffen werden, bevor sie deklariert wurde.✅ Vorteil 4: Loop-Problem gelöst!
javascript
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i); // 0, 1, 2, 3, 4 ✅
}, 100);
}Grund: Jede Iteration erstellt eine neue i-Variable.
📝 Zusammenfassung: let
| Eigenschaft | var | let |
|---|---|---|
| Block-Scope | ❌ | ✅ |
| Hoisting | ✅ (initialisiert mit undefined) | ✅ (aber in TDZ, Zugriff verboten) |
| Doppelte Deklaration | ✅ Erlaubt | ❌ Verboten |
Globale Variable (window.x) | ✅ | ❌ |
2.3 const - Konstanten-Deklaration (read-only, Muss-Initialisierung, Referenztyp-Modifikation)
🔒 const = Konstante (unveränderlich)
const erstellt eine unveränderliche Referenz auf einen Wert.
javascript
const PI = 3.14159;
PI = 3.14; // ❌ TypeError: Assignment to constant variable
const NAME = "Max";
NAME = "Erika"; // ❌ Fehler!📌 Regel 1: Muss sofort initialisiert werden
javascript
const PI; // ❌ SyntaxError: Missing initializer in const declaration
const PI = 3.14159; // ✅ Muss sofort einen Wert zuweisen📌 Regel 2: Primitive Werte sind wirklich unveränderlich
javascript
const age = 25;
age = 26; // ❌ Fehler!
const name = "Max";
name = "Erika"; // ❌ Fehler!📌 Regel 3: Referenztypen (Objekte, Arrays) können inhaltlich geändert werden!
javascript
const person = { name: "Max", alter: 25 };
// ✅ Eigenschaften ändern erlaubt:
person.alter = 26;
person.name = "Erika";
console.log(person); // { name: "Erika", alter: 26 }
// ❌ Aber Neuzuweisung verboten:
person = { name: "Julia" }; // ❌ TypeError!
// ==========================================
const numbers = [1, 2, 3];
// ✅ Array-Methoden erlaubt:
numbers.push(4);
console.log(numbers); // [1, 2, 3, 4]
numbers.pop();
console.log(numbers); // [1, 2, 3]
// ❌ Aber Neuzuweisung verboten:
numbers = [4, 5, 6]; // ❌ TypeError!Grund: const schützt nur die Referenz, nicht den Inhalt.
💡 Objekte/Arrays wirklich unveränderlich machen
javascript
// Objekt komplett einfrieren:
const person = Object.freeze({ name: "Max", alter: 25 });
person.alter = 26; // ❌ Keine Wirkung (im Strict Mode: Fehler)2.4 let / const / var - Drei-Wege-Vergleich
| Eigenschaft | var | let | const |
|---|---|---|---|
| Einführung | JS 1.0 (1995) | ES6 (2015) | ES6 (2015) |
| Block-Scope | ❌ | ✅ | ✅ |
| Hoisting | ✅ (initialisiert) | ✅ (TDZ) | ✅ (TDZ) |
| Doppelte Deklaration | ✅ Erlaubt | ❌ Verboten | ❌ Verboten |
| Neu-Zuweisung | ✅ Erlaubt | ✅ Erlaubt | ❌ Verboten |
| Muss initialisiert werden | ❌ | ❌ | ✅ |
| Empfehlung | ❌ Vermeiden | ✅ Für veränderliche Werte | ✅ Standard (Standard) |
🎯 Wann welches verwenden?
javascript
// ✅ Empfehlung:
// 1. Standardmäßig: const verwenden
const PI = 3.14159;
const API_URL = "https://api.example.com";
const person = { name: "Max" };
// 2. Wenn sich der Wert ändern muss: let verwenden
let count = 0;
count = 1;
let message = "Hallo";
message = "Welt";
// 3. var NIE verwenden (außer in sehr alten Projekten)📊 Umfrage: Wie nutzen professionelle Entwickler?
| Schlüsselwort | Verwendung in modernen Projekten |
|---|---|
| const | ~70% |
| let | ~30% |
| var | ~0% |
2.5 Praxisbeispiel: Block-Scope und Schleifen-Problem
🔥 Beispiel 1: Block-Scope
javascript
// ❌ Schlechter Code (mit var)
var button = document.querySelectorAll("button");
for (var i = 0; i < button.length; i++) {
button[i].addEventListener("click", function() {
console.log("Button " + i + " geklickt"); // Immer die letzte Zahl!
});
}
// ✅ Guter Code (mit let)
const button = document.querySelectorAll("button");
for (let i = 0; i < button.length; i++) {
button[i].addEventListener("click", function() {
console.log(`Button ${i} geklickt`); // Richtig: 0, 1, 2...
});
}🔥 Beispiel 2: Block-Scope bei if/else
javascript
// ❌ Schlechter Code (mit var)
var age = 25;
if (age >= 18) {
var status = "Volljährig";
}
console.log(status); // "Volljährig" (leckt aus dem Block heraus!)
// ✅ Guter Code (mit let)
const age = 25;
if (age >= 18) {
let status = "Volljährig";
console.log(status); // "Volljährig" ✅
}
console.log(status); // ❌ ReferenceError (nicht zugreifbar)🔥 Beispiel 3: const für Konfigurationen
javascript
// ✅ Guter Code (mit const)
const CONFIG = {
apiUrl: "https://api.example.com",
timeout: 5000,
retry: 3
};
// CONFIG = {}; // ❌ Fehler: Neuzuweisung verboten
CONFIG.timeout = 10000; // ✅ Eigenschaft ändern erlaubt
console.log(CONFIG.timeout); // 10000🎉 Zusammenfassung
In diesem Kapitel hast du gelernt:
- ✅ Die Probleme von
var(Hoisting, doppelte Deklaration, kein Block-Scope) - ✅
letfür veränderliche Variablen mit Block-Scope - ✅
constfür Konstanten (Muss-Initialisierung, keine Neuzuweisung) - ✅ Unterschiede zwischen
var,let,const - ✅ Best Practices:
constals Standard,letwenn nötig,varvermeiden
📝 Übung
Schreibe eine Schleife mit
let, die korrekt funktioniert:javascript// Dein Code hier...Erstelle ein Objekt mit
constund ändere eine Eigenschaft:javascript// Dein Code hier...Vergleiche
varvsletim Browser (Console):- Was passiert bei doppelter Deklaration?
- Was passiert bei Block-Scope?
➡️ Nächstes Kapitel
In Kapitel 3 lernen wir Destructuring (Destrukturierung) - eine elegante Methode, um Werte aus Arrays/Objekten zu extrahieren!
