Skip to content

Kapitel 18: ES6 Interviewfragen

18.1 let / const / var Unterschied

📊 Frage 1: Was ist der Unterschied zwischen let, const und var?

Antwort-Struktur:

Eigenschaftvarletconst
Block-Scope❌ Nein✅ Ja✅ Ja
Hoisting✅ Ja (mit undefined)✅ Ja (in TDZ)✅ Ja (in TDZ)
Doppelte Deklaration✅ Erlaubt❌ Verboten❌ Verboten
Neu-Zuweisung✅ Erlaubt✅ Erlaubt❌ Verboten
Muss initialisiert werden❌ Nein❌ Nein✅ Ja
Empfehlung❌ Vermeiden✅ Für veränderliche Werte✅ Standard (Standard)

📝 Musterantwort

Kurzfassung:

  • var hat keinen Block-Scope, nur Funktions-Scope. Es wird hochgezogen (hoisting) mit undefined.
  • let hat Block-Scope, wird hochgezogen, befindet sich aber in der Temporal Dead Zone (TDZ) bis zur Deklaration.
  • const ist wie let, aber die Neu-Zuweisung ist verboten. Muss bei Deklaration initialisiert werden.

Code-Beispiel:

javascript
// var - Probleme
if (true) {
  var x = 10;
}
console.log(x); // 10 ❌ (kein Block-Scope)

// let - Beser
if (true) {
  let y = 20;
}
console.log(y); // ReferenceError ✅ (Block-Scope)

// const - Standard
const PI = 3.14159;
PI = 3.14; // TypeError ✅ (Neu-Zuweisung verboten)

🎯 Folgefragen

Frage: Was ist die Temporal Dead Zone (TDZ)? Antwort: Die TDZ ist der Bereich zwischen dem Beginn des Scopes und der Deklaration der Variablen mit let oder const. In dieser Zone führt der Zugriff auf die Variable zu einem ReferenceError.

javascript
console.log(a); // undefined (Hoisting mit Initialisierung)
var a = 10;

console.log(b); // ReferenceError (TDZ)
let b = 20;

18.2 Arrow Functions vs Normale Funktionen

📊 Frage 2: Was ist der Unterschied zwischen Arrow Functions und normalen Funktionen?

Antwort-Struktur:

AspektNormale FunktionArrow Function
thisDynamisch (wer aufruft)Lexikalisch (umgebender Scope)
arguments✅ Verfügbar❌ Nicht verfügbar
Konstruktor (new)✅ Ja❌ Nein
prototype✅ Hat prototype❌ Kein prototype
SyntaxLängerKürzer (Kurzschreibweise)

📝 Musterantwort

Kurzfassung:

  1. this Verhalten: Normale Funktionen haben ein dynamisches this (wer sie aufruft). Arrow Functions erben this aus dem umgebenden Scope (lexikalisch).
  2. Kein eigenes arguments: Arrow Functions haben kein eigenes arguments Objekt.
  3. Kein Konstruktor: Arrow Functions können nicht mit new aufgerufen werden.
  4. Kürzere Syntax: Arrow Functions erlauben eine kompaktere Schreibweise.

Code-Beispiel:

javascript
// Normale Funktion - this Problem
const person = {
  name: "Max",
  hobbies: ["Sport", "Lesen"],
  printHobbies() {
    this.hobbies.forEach(function(hobby) {
      console.log(`${this.name} mag ${hobby}`); // ❌ this.name ist undefined
    });
  }
};

// Arrow Function - this Problem gelöst
const person2 = {
  name: "Max",
  hobbies: ["Sport", "Lesen"],
  printHobbies() {
    this.hobbies.forEach(hobby => {
      console.log(`${this.name} mag ${hobby}`); // ✅ this.name = "Max"
    });
  }
};

🎯 Folgefragen

Frage: Wann solltest du keine Arrow Function verwenden? Antwort:

  1. Bei Objekt-Methoden (da this das Objekt sein soll).
  2. Bei Klassen-Konstruktoren (da new verwendet wird).
  3. Bei Event Handlern, wo this das DOM-Element sein soll.
javascript
// ❌ Falsch - Arrow Function für Methode
const person = {
  name: "Max",
  greet: () => {
    console.log(`Hallo, ich bin ${this.name}`); // ❌ this ist nicht das Objekt
  }
};

// ✅ Richtig - Normale Funktion für Methode
const person2 = {
  name: "Max",
  greet() {
    console.log(`Hallo, ich bin ${this.name}`); // ✅ this = person2
  }
};

18.3 Promise: Prinzip und Verwendung

📊 Frage 3: Was ist ein Promise und wie funktioniert es?

Antwort-Struktur:

Ein Promise ist ein Objekt, das einen asynchronen Vorgang repräsentiert. Es kann drei Zustände haben:

  1. Pending (Anstehend) - Vorgang läuft noch.
  2. Fulfilled (Erfüllt) - Vorgang erfolgreich abgeschlossen.
  3. Rejected (Abgelehnt) - Vorgang fehlgeschlagen.

📝 Musterantwort

Kurzfassung:

  • Promises dienen dazu, Callback Hell zu vermeiden und asynchrone Code besser lesbar zu machen.
  • Ein Promise wird mit new Promise((resolve, reject) => { ... }) erstellt.
  • Bei Erfolg wird resolve(ergebnis) aufgerufen, bei Fehler reject(fehler).
  • Verwendet wird es mit .then() (bei Erfolg), .catch() (bei Fehler) und .finally() (immer ausgeführt).

Code-Beispiel:

javascript
// Promise erstellen
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve("Daten erfolgreich geladen! ✅");
    } else {
      reject("Fehler beim Laden! ❌");
    }
  }, 1000);
});

// Promise verwenden
myPromise
  .then(result => console.log(result))
  .catch(error => console.error(error))
  .finally(() => console.log("Bereinigung (immer ausgeführt)"));

🎯 Folgefragen

Frage: Was ist der Unterschied zwischen Promise.all() und Promise.race()? Antwort:

  • Promise.all() führt mehrere Promises parallel aus und gibt die Ergebnisse in einem Array zurück. Wenn eines fehlschlägt, wird sofort der catch() Block ausgeführt.
  • Promise.race() gibt das Ergebnis des ersten Promises zurück, das abgeschlossen wird (egal ob Erfolg oder Fehler).
javascript
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = new Promise((resolve, reject) => setTimeout(() => resolve(3), 1000));

// Promise.all()
Promise.all([p1, p2, p3])
  .then(results => console.log(results)); // [1, 2, 3] (nach 1 Sekunde)

// Promise.race()
Promise.race([p1, p3])
  .then(result => console.log(result)); // 1 (sofort)

18.4 Destructuring, Spread-Operator Verwendung

📊 Frage 4: Was ist Destructuring und wie wird es verwendet?

Antwort-Struktur:

Destructuring erlaubt es, Werte aus Arrays oder Objekten in einzelne Variablen zu extrahieren.

TypSyntaxBeschreibung
Array-Destructuringconst [a, b] = array;Extrahiert Werte nach Position
Object-Destructuringconst { name, alter } = obj;Extrahiert Werte nach Namen
Standardwerteconst { name = "Gast" } = obj;Verwendet Standardwert, wenn undefined
Umbenennenconst { name: vorname } = obj;Benennt die Variable um
Rest-Operatorconst [a, ...rest] = array;Sammelt restliche Werte in einem Array/Objekt

📝 Musterantwort

Kurzfassung:

  • Array-Destructuring: Extrahiert Werte basierend auf der Position.
  • Object-Destructuring: Extrahiert Werte basierend auf dem Schlüsselnamen.
  • Vorteile: Kürzere Syntax, bessere Lesbarkeit, Standardwerte, Umbenennen.

Code-Beispiel:

javascript
// Array-Destructuring
const colors = ["rot", "grün", "blau"];
const [first, second] = colors;
console.log(first, second); // "rot", "grün"

// Object-Destructuring
const person = { name: "Max", alter: 25, stadt: "Berlin" };
const { name, alter } = person;
console.log(name, alter); // "Max", 25

// Standardwerte + Umbenennen
const { name: vorname, land = "Deutschland" } = { name: "Max" };
console.log(vorname, land); // "Max", "Deutschland"

// Rest-Operator
const [a, ...rest] = [1, 2, 3, 4, 5];
console.log(a, rest); // 1, [2, 3, 4, 5]

📊 Frage 5: Was ist der Spread-Operator und wie wird er verwendet?

Antwort-Struktur:

Der Spread-Operator (...) entpackt ein iterierbares Element (Array, String, Objekt) in einzelne Elemente.

VerwendungSyntaxBeschreibung
Array kopierenconst copy = [...array];Echte Kopie (Shallow Copy)
Array zusammenführenconst combined = [...arr1, ...arr2];Verbindet Arrays
Objekt kopierenconst copy = { ...obj };Echte Kopie (ES2018+)
Objekt zusammenführenconst combined = { ...obj1, ...obj2 };Verbindet Objekte
String in Arrayconst chars = [...str];Jedes Zeichen wird ein Element

📝 Musterantwort

Kurzfassung:

  • Der Spread-Operator wird verwendet, um Arrays oder Objekte zu kopieren, zusammenzuführen oder in einzelne Elemente zu entpacken.
  • Bei Objekten werden nur die eigenen aufzählbaren Eigenschaften kopiert (Shallow Copy).

Code-Beispiel:

javascript
// Array kopieren + zusammenführen
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const copy = [...arr1]; // Kopie
const combined = [...arr1, ...arr2]; // Zusammenführen
console.log(copy, combined); // [1, 2, 3], [1, 2, 3, 4, 5, 6]

// Objekt kopieren + zusammenführen
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const copyObj = { ...obj1 }; // Kopie
const combinedObj = { ...obj1, ...obj2 }; // Zusammenführen
console.log(copyObj, combinedObj); // { a:1, b:2 }, { a:1, b:2, c:3, d:4 }

// String in Array
const str = "Hallo";
const chars = [...str];
console.log(chars); // ["H", "a", "l", "l", "o"]

🎯 Folgefragen

Frage: Was ist der Unterschied zwischen Rest-Parameter und Spread-Operator? Antwort:

  • Rest-Parameter (...args): Sammelt mehrere Argumente in einem Array (bei Funktionsparametern).
  • Spread-Operator (...): Entpackt ein Array oder Objekt in einzelne Elemente.
javascript
// Rest-Parameter
function sum(...numbers) {
  return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3)); // 6

// Spread-Operator
const numbers = [1, 2, 3];
console.log(...numbers); // 1 2 3
console.log(Math.max(...numbers)); // 3

18.5 Asynchrone Programmierung: Entwicklung (Callback → Promise → async/await)

📊 Frage 6: Beschreibe die Entwicklung der asynchronen Programmierung in JavaScript.

Antwort-Struktur:

StufeTechnologieBeschreibungProbleme
1. CallbacksCallback-FunktionenÜbergeben einer Funktion als ArgumentCallback Hell (Verschachtelung)
2. Promisesnew Promise()Objekt zur Repräsentation asynchroner VorgängeEtwas komplexe Syntax
3. async/awaitasync / awaitSyntax-Zucker über PromisesKeine (modernste Methode)

📝 Musterantwort

Kurzfassung:

  1. Callbacks: Die älteste Methode. Eine Funktion wird als Argument übergeben und später aufgerufen. Problem: Callback Hell (tiefe Verschachtelung).
  2. Promises: introduces new Promise(), .then(), .catch(). Vorteil: Bessere Lesbarkeit, Fehlerbehandlung zentralisiert.
  3. async/await: Eingeführt in ES2017. Macht asynchronen Code wie synchronen Code lesbar. Verwendet try...catch für Fehlerbehandlung.

Code-Beispiel:

javascript
// 1. Callbacks (Callback Hell)
function getUserCallback() {
  getUserId((userId) => {
    getUserName(userId, (name) => {
      console.log(name); // Tief verschachtelt 😱
    });
  });
}

// 2. Promises
function getUserPromise() {
  getUserId()
    .then(userId => getUserName(userId))
    .then(name => console.log(name))
    .catch(error => console.error(error));
}

// 3. async/await (modernste Methode)
async function getUserAsync() {
  try {
    const userId = await getUserId();
    const name = await getUserName(userId);
    console.log(name);
  } catch (error) {
    console.error(error);
  }
}

🎯 Folgefragen

Frage: Was macht await? Antwort: await pausiert die Ausführung einer async Funktion, bis das Promise aufgelöst wird. Es kann nur innerhalb von async Funktionen verwendet werden.

javascript
async function fetchData() {
  console.log("Laden...");
  const result = await somePromise; // Pausiert hier
  console.log("Fertig!", result); // Macht weiter, wenn Promise aufgelöst
}

🎉 Zusammenfassung

In diesem Kapitel hast du gelernt:

  • let / const / var Unterschied (Scope, Hoisting, TDZ)
  • Arrow Functions vs Normale Funktionen (this Verhalten, arguments, Konstruktor)
  • Promise: Prinzip und Verwendung (Pending, Fulfilled, Rejected, .then(), .catch(), .finally())
  • Destructuring, Spread-Operator Verwendung (Array/Object Destructuring, Rest-Operator, Kopieren, Zusammenführen)
  • Asynchrone Programmierung: Entwicklung (Callback → Promise → async/await)

📝 Übung

  1. Interviewfrage simulieren:

    javascript
    // Bereite eine Antwort auf die Frage vor:
    // "Was ist der Unterschied zwischen Promise.all() und Promise.race()?"
  2. Code-Beispiel erstellen:

    javascript
    // Erstelle ein Beispiel, das Destructuring, Spread-Operator und Arrow Functions kombiniert
  3. async/await vs Promise:

    javascript
    // Schreibe dieselbe asynchrone Funktion einmal mit Promises und einmal mit async/await

➡️ Nächstes Kapitel

In Kapitel 19 lernen wir ES6+ neuere Versionen (ES7~ES13) - optionale Verkettung, Nullish Coalescing, logische Zuweisungsoperatoren, Zahlen-Trennzeichen und mehr!

Frei für alle Anfänger