Häufig gestellte Fragen und Antworten zu JavaScript-Interviews

Die Beherrschung von JavaScript ist ein entscheidender Vorteil, um als Softwareentwickler erfolgreich zu sein. Im Folgenden gehen wir auf einige häufige Fragen ein, die in JavaScript-Interviews gestellt werden könnten.

JavaScript hat sich als eine der meistgenutzten Sprachen in der Webentwicklung etabliert. Es wird heutzutage für die Entwicklung fast jeder Art von Anwendung verwendet.

Bevor wir uns den typischen Interviewfragen widmen, betrachten wir die Vorteile, die das Erlernen von JavaScript bietet.

JavaScript ist eine schlanke, interpretierte oder Just-in-Time-kompilierte Programmiersprache und eine der Kernkomponenten des World Wide Web. Es gibt noch zwei weitere essenzielle Sprachen des Internets, die Sie kennen sollten. Sollten Sie diese nicht kennen, ist jetzt der richtige Zeitpunkt, um sie zu recherchieren.

JavaScript wurde ursprünglich für das Web entwickelt, ist aber heute vielseitiger einsetzbar. Dank Umgebungen wie Node.js und Deno kann es auf nahezu jeder Plattform laufen.

Lassen Sie uns einige der Hauptvorteile dieser Programmiersprache genauer untersuchen.

Vorteile von JavaScript

  • Leichter Einstieg: JavaScript ist auch ohne vorherige Programmierkenntnisse zugänglich.
  • Umfangreiche Community: Eine große und hilfsbereite Community steht Ihnen bei Fragen zur Seite.
  • Reichhaltiges Ökosystem: Eine Vielzahl von Bibliotheken und Frameworks beschleunigen die Anwendungsentwicklung.
  • Vielseitigkeit: JavaScript ermöglicht die Entwicklung von Frontend-, Backend-, Android- und iOS-Anwendungen sowie anderer Typen. Es ist besonders stark im Bereich der Webentwicklung.

Welche Datentypen existieren in JavaScript?

Datentypen definieren die Art von Daten, die gespeichert werden können. Sie unterscheiden sich von Programmiersprache zu Programmiersprache. In JavaScript sind acht Datentypen definiert. Sehen wir uns diese einmal im Detail an:

  • Number (Zahl)
  • String (Zeichenkette)
  • Boolean (Boolescher Wert)
  • Undefined (Undefiniert)
  • Null
  • BigInt
  • Symbol
  • Object (Objekt)

Alle Datentypen außer dem Objekttyp werden als primitive Werte betrachtet und sind unveränderlich.

Welche integrierten Methoden bietet JavaScript?

Die integrierten Methoden in JavaScript sind spezifisch für jeden Datentyp. Wir greifen auf diese Methoden über die jeweiligen Datentypen zu. Betrachten wir einige Beispiele für verschiedene Datentypen und Datenstrukturen:

  • Number (Zahl)
  • String (Zeichenkette)
    • toLowerCase (in Kleinbuchstaben umwandeln)
    • startsWith (beginnt mit)
    • charAt (Zeichen an Position)
  • Array

Für jeden Datentyp gibt es zahlreiche weitere integrierte Methoden. Es empfiehlt sich, die Referenzen für alle integrierten Methoden der verschiedenen Datentypen und Datenstrukturen einzusehen.

Wie wird ein Array in JavaScript erstellt?

Arrays sind eine der fundamentalen Datenstrukturen in JavaScript. JavaScript-Arrays sind dynamisch und können verschiedene Datentypen speichern. Schauen wir uns an, wie man in JavaScript Arrays erstellt.

Arrays können mit eckigen Klammern [] deklariert werden. Diese Methode ist einfach und schnell:

// Leeres Array
const arr = [];

// Array mit zufälligen Werten
const randomArr = [1, "Eins", true];

console.log(arr, randomArr);

Alternativ kann man ein Array mit dem Array-Konstruktor erstellen. Diese Methode wird jedoch in der Praxis seltener genutzt:

// Leeres Array
const arr = new Array();

// Array mit zufälligen Werten
const randomArr = new Array(1, "Eins", true);

console.log(arr, randomArr);

JavaScript-Arrays sind veränderbar, d.h. sie können nach der Erstellung nach Bedarf modifiziert werden.

Wie erstelle ich ein Objekt in JavaScript?

Neben Arrays sind Objekte eine weitere wesentliche Datenstruktur in JavaScript. Objekte speichern Daten in Form von Schlüssel-Wert-Paaren, wobei der Schlüssel unveränderlich und der Wert beliebigen Typs sein kann. Hier ist, wie man Objekte in JavaScript definiert:

Objekte können mit geschweiften Klammern {} erstellt werden, eine einfache und schnelle Methode:

// Leeres Objekt
const object = {};

// Objekt mit zufälligen Werten
const randomObject = { 1: 2, eins: "Zwei", true: false };

console.log(object, randomObject);

Eine weitere Möglichkeit ist die Verwendung des Objektkonstruktors, der in der Praxis aber weniger häufig eingesetzt wird:

// Leeres Objekt
const object = new Object();

// Objekt mit zufälligen Werten
const randomObject = new Object();
randomObject[1] = 2;
randomObject["eins"] = "Zwei";
randomObject[true] = false;

console.log(object, randomObject);

JavaScript-Objekte sind ebenfalls veränderbar, was bedeutet, dass ihre Eigenschaften nach der Erstellung modifiziert werden können, wie im zweiten Beispiel gezeigt.

Wie wird JavaScript-Code debuggt?

Das Debuggen ist ein wichtiger Bestandteil der Softwareentwicklung und kann je nach Programmiersprache und Projekt variieren. Im Folgenden werden einige gängige Methoden zum Debuggen von JavaScript betrachtet:

1. Protokollierung (Logging)

Die Verwendung von `console.log`-Anweisungen an verschiedenen Stellen im Code kann helfen, Fehler zu identifizieren. Sobald ein Fehler auftritt, stoppt die Ausführung der nachfolgenden Codezeilen.

Diese Methode ist insbesondere für kleinere Projekte nützlich und eine gängige Technik zum Debuggen in verschiedenen Programmiersprachen.

2. Entwicklertools

JavaScript wird häufig für Webanwendungen eingesetzt, daher verfügen die meisten Browser über integrierte Entwicklertools zum Debuggen von JavaScript-Code.

Eine gängige Methode ist das Setzen von Haltepunkten (Breakpoints) in den Entwicklertools. Diese Haltepunkte stoppen die Ausführung des JavaScripts an einer bestimmten Stelle und geben detaillierte Informationen über den Ausführungszustand zu diesem Zeitpunkt aus.

Durch das Setzen von Haltepunkten in der Nähe von vermuteten Fehlerstellen können wir die Fehlerursache effektiv finden. Dies ist besonders effizient für das Debuggen von JavaScript-Webanwendungen.

3. Integrierte Entwicklungsumgebungen (IDEs)

IDEs wie VS Code unterstützen das Debuggen von JavaScript mit Haltepunkten. Die Debugging-Funktionen können je nach verwendeter IDE variieren, sind aber in den meisten Umgebungen vorhanden.

Wie wird JavaScript-Code in eine HTML-Datei eingebunden?

JavaScript-Code wird mit dem `script`-Tag in HTML eingebunden. Hier ist ein Beispiel:

<!DOCTYPE html>
<html lang="de">
  <head>
    <title>wdzwdz</title>
  </head>
  <body>
    <h1>wdzwdz</h1>

    <script>
      // Hier kommt JavaScript-Code hin
      console.log("Dies ist JavaScript-Code");
    </script>
  </body>
</html>

Was sind Cookies?

Cookies sind Schlüssel-Wert-Paare, die zur Speicherung kleinerer Datenmengen verwendet werden. Die enthaltenen Daten können jeglicher Art sein. Für Cookies kann eine Ablaufzeit definiert werden, nach der sie automatisch gelöscht werden. Cookies werden oft verwendet, um Benutzerinformationen zu speichern.

Cookies bleiben erhalten, auch wenn die Seite aktualisiert wird, bis sie entweder gelöscht werden oder ihre Ablaufzeit erreicht ist. Die Cookies jeder Webanwendung oder Webseite lassen sich über die Entwicklertools eines Browsers inspizieren.

Wie kann ein Cookie gelesen werden?

Cookies können in JavaScript mit `document.cookie` ausgelesen werden. Dies gibt eine Zeichenkette mit allen gesetzten Cookies zurück:

console.log("Alle Cookies", document.cookie);

Wenn keine Cookies vorhanden sind, wird eine leere Zeichenkette zurückgegeben.

Wie werden Cookies erstellt und gelöscht?

Cookies können erstellt werden, indem ein Schlüssel-Wert-Paar der Eigenschaft `document.cookie` zugewiesen wird. Hier ein Beispiel:

document.cookie = "eins=Eins;";

In dieser Syntax ist „eins“ der Cookie-Schlüssel und „Eins“ sein Wert. Zusätzliche Attribute wie „Domain“, „Pfad“, „Ablaufdatum“ usw. können dem Cookie hinzugefügt werden, wobei jedes durch ein Semikolon (;) getrennt wird. Alle Attribute sind optional.

Ein Beispiel mit zusätzlichen Attributen:

document.cookie = "eins=Eins;expires=Jan 31 2023;path=/;";

Im obigen Code haben wir dem Cookie ein Ablaufdatum und einen Pfad hinzugefügt. Wird das Ablaufdatum nicht definiert, wird der Cookie nach Sitzungsende gelöscht. Der Standardpfad ist der Pfad der aktuellen Datei. Das Format des Ablaufdatums muss GMT sein.

Hier ist, wie man mehrere Cookies erstellt:

document.cookie = "eins=Eins;expires=Jan 31 2023;path=/;";
document.cookie = "zwei=Zwei;expires=Jan 31 2023;path=/;";
document.cookie = "drei=Drei;expires=Jan 31 2023;path=/;";

Cookies werden nicht überschrieben, solange der Schlüssel oder Pfad bei der Erstellung mehrerer Cookies unterschiedlich ist. Wenn jedoch Schlüssel und Pfad identisch sind, wird der vorherige Cookie überschrieben. Sehen wir uns folgendes Beispiel an, das den zuvor gesetzten Cookie überschreibt:

document.cookie = "eins=Eins;expires=Jan 31 2023;path=/;";
document.cookie = "eins=Zwei;path=/;";

Wir haben das Ablaufdatum des Cookies entfernt und den Wert geändert.

Verwenden Sie beim Testen des Codes ein zukünftiges Datum als Ablaufdatum, damit er richtig funktioniert. Wenn Sie das gleiche Datum, den 31. Januar 2023, auch nach dem 31. Januar 2023 verwenden, werden keine Cookies erstellt.

Wir haben gesehen, wie Cookies erstellt und aktualisiert werden. Schauen wir uns nun an, wie sie gelöscht werden können:

Das Löschen von Cookies ist einfach. Setzen Sie einfach das Ablaufdatum des Cookies auf ein Datum in der Vergangenheit. Hier ist ein Beispiel:

// Cookies erstellen
document.cookie = "eins=Eins;expires=Jan 31 2023;path=/;";
document.cookie = "zwei=Zwei;expires=Jan 31 2023;path=/;";
document.cookie = "drei=Drei;expires=Jan 31 2023;path=/;";

// Den letzten Cookie löschen
document.cookie = "drei=Drei;expires=Jan 1 2023;path=/;";

Der letzte Cookie ist nicht mehr in den Cookies enthalten, da er in der letzten Codezeile gelöscht wurde. Das war eine kurze Einführung zu Cookies.

Welche verschiedenen JavaScript-Frameworks gibt es?

Es gibt eine Vielzahl von JavaScript-Frameworks. React, Vue und Angular sind beliebte Optionen für die UI-Entwicklung. Für die serverseitige Entwicklung gibt es Frameworks wie Express, Koa und Nest.js. Next.js und Gatsby werden verwendet, um statische Webseiten zu erstellen. Mobile Apps können mit React Native oder Ionic entwickelt werden. Diese Liste enthält einige gängige Frameworks, es gibt aber noch viele mehr. Es empfiehlt sich, diese zu erkunden, wenn der Bedarf entsteht.

Closures in JavaScript

Ein Closure ist eine Funktion, die mit ihrem lexikalischen Scope und der äußeren lexikalischen Umgebung gebündelt ist. Closures erlauben den Zugriff auf Daten aus dem äußeren Scope. Sie werden erzeugt, wenn Funktionen deklariert werden.

function outer() {
  const a = 1;
  function inner() {
    // Daten aus dem äußeren Funktionsscope können hier aufgerufen werden
    // Die Daten sind auch dann noch verfügbar, wenn wir diese Funktion außerhalb von "outer" ausführen
    // da die Closure beim Erstellen der Funktion "inner" geformt wurde
    console.log("Zugriff auf 'a' innerhalb von 'inner'", a);
  }
  return inner;
}

const innerFn = outer();
innerFn();

Closures sind ein häufig verwendetes Konzept in JavaScript-Anwendungen. Möglicherweise haben Sie sie bereits verwendet, ohne sich dessen bewusst zu sein. Es gibt noch viel mehr über Closures zu entdecken. Es ist ratsam, dieses Konzept vollständig zu verstehen.

Hoisting in JavaScript

Hoisting ist ein JavaScript-Mechanismus, der Variablendeklarationen, Funktionsdeklarationen und Klassendeklarationen an den Anfang ihres jeweiligen Scopes verschiebt, bevor der Code ausgeführt wird.

// Zugriff auf `name`, bevor es deklariert wird
console.log(name);

// Deklarieren und Initialisieren von `name`
var name = "wdzwdz";

Dieser Code wird nicht zu einem Fehler führen. In den meisten anderen Programmiersprachen würde hier ein Fehler auftreten. Die Ausgabe ist ‚undefined‘, da das Hoisting nur die Deklarationen an den Anfang verschiebt und die Initialisierung erst in Zeile 3 erfolgt.

Ändern Sie `var` in `let` oder `const` und führen Sie den Code erneut aus:

// Zugriff auf `name`, bevor es deklariert wird
console.log(name);

// Deklarieren und Initialisieren von `name`
const name = "wdzwdz";

Sie erhalten nun einen ‚ReferenceError‘, der besagt, dass Sie nicht auf die Variable zugreifen können, bevor sie initialisiert wird.

ReferenceError: Cannot access 'name' before initialization

`let` und `const` wurden in ES6 eingeführt und verhindern den Zugriff auf Variablen vor ihrer Initialisierung. Variablen, die mit `let` oder `const` deklariert werden, befinden sich in der Temporal Dead Zone (TDZ), bis sie initialisiert werden. Variablen aus der TDZ können nicht verwendet werden.

Currying in JavaScript

Currying ist eine Technik, mit der Funktionen mit mehreren Parametern in Funktionen mit weniger Parametern umgewandelt werden, die über mehrere Aufrufe ausgeführt werden können. Dadurch kann eine Funktion `add(a, b, c, d)` in `add(a)(b)(c)(d)` umgewandelt werden. Hier ist ein Beispiel:

function getCurryCallback(callback) {
  return function (a) {
    return function (b) {
      return function (c) {
        return function (d) {
          return callback(a, b, c, d);
        };
      };
    };
  };
}

function add(a, b, c, d) {
  return a + b + c + d;
}

const curriedAdd = getCurryCallback(add);

// Aufruf von curriedAdd
console.log(curriedAdd(1)(2)(3)(4));

Die `getCurryCallback`-Funktion kann generalisiert werden, sodass sie für jede Funktion verwendet werden kann, um sie in Currying-Callables umzuwandeln. Weitere Details finden Sie auf JavaScript Info.

Unterschied zwischen Dokument und Fenster

Das Fenster ist das Objekt der obersten Ebene in einem Browser. Es enthält alle Informationen über das Browserfenster, wie z. B. Verlauf, Standort, Navigator, usw. Es ist global in JavaScript verfügbar und kann ohne Imports direkt im Code verwendet werden. Auf die Eigenschaften und Methoden des Fensterobjekts kann auch ohne das vorangestellte ‚Fenster‘ zugegriffen werden.

Das Dokument ist ein Teil des Fensterobjekts. Der gesamte auf der Webseite geladene HTML-Code wird in ein Dokumentobjekt umgewandelt. Das Dokumentobjekt bezieht sich auf ein spezielles HTMLDocument-Element, das wie alle HTML-Elemente weitere Eigenschaften und Methoden hat.

Das Fensterobjekt repräsentiert das Browserfenster und das Dokumentobjekt repräsentiert das in diesem Fenster geladene HTML-Dokument.

Unterschied zwischen clientseitig und serverseitig

Die Clientseite bezieht sich auf den Endbenutzer, der die Anwendung nutzt, während die Serverseite sich auf den Webserver bezieht, auf dem die Anwendung bereitgestellt wird.

Im Frontend-Kontext sind die Browser auf den Computern der Nutzer die Clientseite und Cloud-Dienste die Serverseite.

Unterschied zwischen innerHTML und innerText

Sowohl `innerHTML` als auch `innerText` sind Eigenschaften von HTML-Elementen und werden verwendet, um den Inhalt dieser Elemente zu ändern.

`innerHTML` kann ein HTML-String zugewiesen werden, der dann als normales HTML gerendert wird. Hier ein Beispiel:

const titleEl = document.getElementById("title");

titleEl.innerHTML = '<span style="color:orange;">wdzwdz</span>';

Wenn Sie Ihrem HTML-Code ein Element mit der ID „title“ hinzufügen und das obige Skript in eine JavaScript-Datei einfügen, wird „wdzwdz“ in orange dargestellt. Wenn Sie das Element untersuchen, stellen Sie fest, dass es in einem `span`-Tag enthalten ist. `innerHTML` interpretiert den HTML-String und rendert ihn als HTML.

Im Gegensatz dazu nimmt `innerText` einen einfachen String und gibt ihn genau so aus, wie er ist. Es interpretiert HTML-Code nicht. Wenn Sie im obigen Code `innerHTML` durch `innerText` ersetzen und die Ausgabe betrachten, sehen Sie genau den bereitgestellten String:

const titleEl = document.getElementById("title");

titleEl.innerText="<span style="color:orange;">wdzwdz</span>";

Die Ausgabe auf der Webseite wird genau so angezeigt, wie sie als String definiert wurde.

Unterschied zwischen let und var

Die Schlüsselwörter `let` und `var` werden in JavaScript verwendet, um Variablen zu deklarieren. Das Schlüsselwort `let` wurde in ES6 eingeführt.

`let` ist blockorientiert und `var` ist funktionsorientiert.

{
  let a = 2;
  console.log("Innerhalb des Blocks", a);
}
console.log("Außerhalb des Blocks", a);

Wenn Sie diesen Code ausführen, erhalten Sie einen Fehler in der letzten Zeile, da auf `let a` außerhalb des Blocks nicht zugegriffen werden kann, da es blockorientiert ist. Ändern Sie nun `let` in `var` und führen Sie es erneut aus:

{
  var a = 2;
  console.log("Innerhalb des Blocks", a);
}
console.log("Außerhalb des Blocks", a);

Es wird kein Fehler auftreten, da wir auf die Variable `a` auch außerhalb des Blocks zugreifen können. Ersetzen wir nun den Block durch eine Funktion:

function sample() {
  var a = 2;
  console.log("Innerhalb der Funktion", a);
}
sample();
console.log("Außerhalb der Funktion", a);

Sie erhalten einen Referenzfehler, wenn Sie den obigen Code ausführen, da wir außerhalb der Funktion nicht auf `var a` zugreifen können, da es sich um einen Funktionsscope handelt.

Variablen, die mit `var` deklariert wurden, können neu deklariert werden. Das ist mit `let` nicht möglich. Hier ist ein Beispiel:

var a = "wdzwdz";
var a = "Chandan";
console.log(a);
let a = "wdzwdz";
let a = "Chandan";
console.log(a);

Der erste Codeabschnitt führt nicht zu einem Fehler, und der Wert von `a` wird auf den zuletzt zugewiesenen Wert aktualisiert. Der zweite Codeabschnitt gibt einen Fehler aus, da Variablen nicht mit `let` neu deklariert werden können.

Unterschied zwischen Session Storage und Local Storage

Session Storage und Local Storage werden verwendet, um Informationen auf den Computern der Benutzer zu speichern, auf die auch ohne Internetverbindung zugegriffen werden kann. Beide speichern Schlüssel-Wert-Paare, wobei sowohl Schlüssel als auch Werte in Zeichenketten konvertiert werden, wenn ein anderer Datentyp angegeben wird.

Der Session Storage wird nach Beendigung der Sitzung (wenn der Browser geschlossen wird) gelöscht, während der Local Storage nur gelöscht wird, wenn er explizit gelöscht wird.

Session Storage und Local Storage können mit den Objekten `sessionStorage` bzw. `localStorage` manipuliert werden.

Was ist NaN in JavaScript?

NaN steht für „Not a Number“ (keine Zahl). Es zeigt an, dass ein Wert in JavaScript keine gültige Zahl ist. NaN tritt unter bestimmten Umständen auf, z.B. bei `0/0`, `undefined * 2`, `1 + undefined`, `null * undefined` usw.

Was ist Lexical Scoping?

Lexical Scoping bezieht sich auf den Zugriff auf Variablen aus dem Scope ihrer Eltern. Wenn wir eine Funktion mit zwei inneren Funktionen haben, kann die innerste Funktion auf die Scope-Variablen ihrer beiden übergeordneten Funktionen zugreifen. Ebenso kann die zweite Ebene auf die Scope der äußeren Funktion zugreifen. Betrachten wir dies anhand eines Beispiels:

function outermost() {
  let a = 1;
  console.log(a);
  function middle() {
    let b = 2;
    // `a` ist hier zugänglich
    console.log(a, b);
    function innermost() {
      let c = 3;
      // sowohl `a` als auch `b` sind hier zugänglich
      console.log(a, b, c);
    }
    innermost();
  }
  middle();
}
outermost();

JavaScript verwendet eine Scope-Kette, um die Variable zu finden, wenn wir irgendwo im Code auf sie zugreifen. Zuerst wird die Variable im aktuellen Scope und dann im Scope der Eltern bis zum globalen Scope überprüft.

Was ist Wertübergabe und Referenzübergabe?

Wertübergabe (Pass-by-Value) und Referenzübergabe (Pass-by-Reference) sind zwei Methoden, um Argumente an eine Funktion in JavaScript zu übergeben.

Wertübergabe: Hier wird eine Kopie der Originaldaten an die Funktion übergeben. Änderungen innerhalb der Funktion beeinflussen die ursprünglichen Daten nicht. Hier ist ein Beispiel:

function sample(a) {
  // Ändern des Wertes von `a`
  a = 5;
  console.log("Innerhalb der Funktion", a);
}
let a = 3;
sample(a);
console.log("Außerhalb der Funktion", a);

Wie man sieht, ändert sich der ursprüngliche Wert von `a` nicht, obwohl er innerhalb der Funktion geändert wurde.

Referenzübergabe: Hier wird eine Referenz auf die Daten an die Funktion übergeben. Änderungen innerhalb der Funktion wirken sich auf die ursprünglichen Daten aus:

function sample(arr) {
  // Hinzufügen eines neuen Wertes zum Array
  arr.push(3);
  console.log("Innerhalb der Funktion", arr);
}
let arr = [1, 2];
sample(arr);
console.log("Außerhalb der Funktion", arr);

Hier ändert sich der ursprüngliche Wert von `arr`, wenn wir ihn innerhalb der Funktion ändern.

Hinweis: Alle primitiven Datentypen werden per Wert übergeben, und nicht-primitive Datentypen per Referenz.

Was ist Memoization?

Memoization ist eine Technik, um berechnete Werte in einem Cache zu speichern, um sie bei Bedarf ohne erneute Berechnung zu nutzen. Das führt zu einer beschleunigten Ausführung des Codes, wenn die Berechnung aufwendig ist. Es gibt einen Speicherkompromiss, der im Vergleich zur Zeitersparnis in der Regel kein Problem darstellt.

const memo = {};
function add(a, b) {
  const key = `${a}-${b}`;

  // Überprüfen, ob der Wert bereits berechnet wurde
  if (memo[key]) {
    console.log("Keine Neuberechnung");
    return memo[key];
  }

  // Hinzufügen des neu berechneten Wertes zum Cache
  // Hier ist der Cache ein einfaches globales Objekt
  memo[key] = a + b;
  return memo[key];
}

console.log(add(1, 2));
console.log(add(2, 3));
console.log(add(1, 2));

Dies ist ein einfaches Beispiel, um Memoization zu demonstrieren. Das Addieren von zwei Zahlen ist keine rechenintensive Aufgabe, es dient lediglich der Veranschaulichung.

Was ist der Rest-Parameter?

Der Rest-Parameter wird verwendet, um alle verbleibenden Parameter einer Funktion aufzunehmen. Nehmen wir an, wir haben eine Funktion, die mindestens zwei Argumente akzeptiert und optional weitere. Da wir die maximale Anzahl an Argumenten nicht kennen, können wir die ersten beiden Parameter mit normalen Variablen aufnehmen und alle anderen mit dem Rest-Parameter unter Verwendung des Rest-Operators:

function sample(a, b, ...rest) {
  console.log("Rest Parameter", rest);
}

sample(1, 2, 3, 4, 5);

Der Rest-Parameter im obigen Beispiel ist ein Array der letzten drei Argumente. Dadurch können wir beliebig viele Argumente an eine Funktion übergeben.

Eine Funktion kann nur einen Rest-Parameter haben, und dieser sollte als letzter Parameter in der Reihenfolge stehen.

Was ist Object Destructuring?

Object Destructuring wird verwendet, um auf Variablen eines Objekts zuzugreifen und sie Variablen mit denselben Namen wie die Objektschlüssel zuzuweisen. Hier ein Beispiel:

const object = { a: 1, b: 2, c: 3 };

// Objekt Destructuring
const { a, b, c } = object;

// Nun können a, b, c als normale Variablen verwendet werden
console.log(a, b, c);

Die Namen der destrukturierten Variablen können auch gleich beim Destrukturieren geändert werden:

const object = { a: 1, b: 2, c: 3 };

// Umbenennen von `a` und `b`
const { a: changedA, b: changedB, c } = object;

// Nun können changedA, changedB, c als normale Variablen verwendet werden
console.log(changedA, changedB, c);

Was ist Array Destructuring?

Array Destructuring dient dazu, auf Variablen aus dem Array zuzugreifen und sie Variablen zuzuweisen. Hier ist ein Beispiel:

const array = [1, 2, 3];

// Array Destructuring
// Die Zuordnung basiert auf dem Index des Arrays
const [a, b, c] = array;

// Nun können a, b, c als normale Variablen verwendet werden
console.log(a, b, c);

Was sind Event Capturing und Event Bubbling?

Event Capturing und Event Bubbling sind zwei Mechanismen zur Ereignisweitergabe im HTML DOM. Wenn zwei HTML-Elemente ineinander verschachtelt sind und ein Ereignis auf dem inneren Element auftritt, entscheidet der Ereignisausbreitungsmodus über die Ausführungsreihenfolge der Event-Handler.

Event Bubbling: Hier wird zuerst der Event-Handler des Zielelements, dann des Elternelements usw. bis zum obersten Element ausgeführt. Dies ist das Standardverhalten aller Ereignisse.

Event Capturing: Hier muss explizit angegeben werden, dass dieser Modus verwendet werden soll. Dies kann beim Hinzufügen des Event-Listeners geschehen. Bei aktivierter Ereigniserfassung werden die Ereignisse in folgender Reihenfolge ausgelöst:

  • Die Ereignisse werden vom obersten Element zum Zielelement hinunter ausgeführt.
  • Das Ereignis auf dem Zielelement wird erneut ausgeführt.
  • Event Bubbling findet dann wieder statt, bis das oberste Element erreicht ist.

Die Ereignisweitergabe kann durch Aufruf der Methode `event.stopPropagation()` innerhalb des Event-Handlers gestoppt werden.

Was sind Promises in JavaScript?

Das Promise-Objekt wird für asynchrone Operationen verwendet, die entweder mit Erfolg oder Fehler beendet werden.

Ein Promise kann sich in einem von drei Zuständen befinden:

  • pending: Der Vorgang ist noch nicht abgeschlossen.
  • fulfilled: Der Vorgang wurde erfolgreich beendet. Im Erfolgsfall erhalten wir ein Ergebnis.
  • rejected: Der Vorgang wurde mit einem Fehler abgeschlossen. Wir erhalten den Grund für den Fehler.

Hier sind zwei Beispiele für erfolgreiche und fehlerhafte Promises:

// Promise, das erfolgreich abgeschlossen wird
const successPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve({ message: "Erfolgreich abgeschlossen" });
  }, 300);
});
successPromise
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.log(error);
  });

// Promise, das mit einem Fehler abgeschlossen wird
const failurePromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error("Promise wird zur Demonstration abgelehnt"));
  }, 300);
});
failurePromise
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.log(error);
  });

Promises können verkettet werden. Die Daten des vorherigen Promises werden an die nächste `then`-Callback-Funktion übergeben.

Erkläre die verschiedenen Arten von Scope in JavaScript

In JavaScript gibt es zwei Arten von Scope: den globalen Scope und den lokalen Scope.

Möglicherweise haben Sie auch von Funktionsscope und Blockscope gehört. Das sind lokale Scopes für `var` bzw. `let` und `const`.

Was sind selbstaufrufende Funktionen?

Selbstaufrufende Funktionen sind anonyme Funktionen, die unmittelbar nach ihrer Definition ausgeführt werden. Hier sind ein paar Beispiele:</