Skip to content

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 Ort

Problem: 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

Eigenschaftvarlet
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

Eigenschaftvarletconst
EinführungJS 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üsselwortVerwendung 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)
  • let für veränderliche Variablen mit Block-Scope
  • const für Konstanten (Muss-Initialisierung, keine Neuzuweisung)
  • ✅ Unterschiede zwischen var, let, const
  • ✅ Best Practices: const als Standard, let wenn nötig, var vermeiden

📝 Übung

  1. Schreibe eine Schleife mit let, die korrekt funktioniert:

    javascript
    // Dein Code hier...
  2. Erstelle ein Objekt mit const und ändere eine Eigenschaft:

    javascript
    // Dein Code hier...
  3. Vergleiche var vs let im 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!

Frei für alle Anfänger