Quiz:Fortgeschrittene JS‑Fehlerbeherrschung
Sind Ihre Ausnahmen wirklich außergewöhnlich?
Glaubst du, du kennst JavaScript‑Fehler in- und auswendig?
- Teste dein Know‑how im Fehler‑Handling! 💥
- Kein Login oder Registrierung nötig. ✨
- Multiple‑Choice. 🤖 … Das sind keine gewöhnlichen try‑catch‑Fragen!
Was gibt JSON.stringify(error) zurück?
const error = new Error('Oops');console.log(JSON.stringify(error));Error-Objekte haben nicht aufzählbare Eigenschaften (message, name, stack), daher gibt JSON.stringify() {} zurück. Das ist ein häufiger Stolperstein beim Senden von Fehlern in API‑Antworten. Verwende JSON.stringify(error, Object.getOwnPropertyNames(error)) oder erstelle stattdessen ein einfaches Objekt.
Welche Eigenschaften eines Error-Objekts sind aufzählbar?
Was ist der Unterschied zwischen den beiden?
const err = new Error('Test');console.log(err);console.log(JSON.stringify(err));console.log(err) zeigt den Fehler mit seiner Nachricht und dem Stack‑Trace, weil die Konsole eine spezielle Behandlung für Error‑Objekte hat. JSON.stringify(err) liefert '{}', weil Error‑Eigenschaften nicht aufzählbar sind. Dieser Unterschied bringt viele Entwickler beim Debuggen von APIs durcheinander.
Vergleiche die spezielle Objektanzeige der Konsole mit der JSON-Serialisierung.
Was sind die Ergebnisse dieser Prüfungen?
class CustomError extends Error {}const err = new CustomError('test');
console.log(err instanceof CustomError);console.log(err instanceof Error);console.log(err instanceof Object);Alle drei geben true zurück. CustomError erweitert Error, das wiederum Object erweitert. Der instanceof‑Operator prüft die gesamte Prototypkette, sodass eine CustomError‑Instanz auch eine Instanz von Error und Object ist.
instanceof folgt der gesamten Prototypkette.
Angenommen, ein Same-Origin-iframe erzeugt ein Error-Objekt und übergibt es als iframeError an das übergeordnete Fenster. Was kann diese Prüfung im übergeordneten Fenster ergeben?
console.log(iframeError instanceof Error);instanceof kann über Realm-Grenzen hinweg false liefern, weil jeder Realm einen eigenen Error-Konstruktor und Prototyp besitzt. Object.prototype.toString.call(obj) kann bei gewöhnlichen Error-Objekten helfen, doch Symbol.toStringTag kann das Ergebnis fälschen. Es ist kein Echtheitsnachweis für nicht vertrauenswürdige Werte.
Unterschiedliche Ausführungskontexte besitzen eigene Error-Konstruktoren.
Was passiert, wenn du eine Zeichenkette wirfst?
try { throw "Oops!";} catch (e) { console.log(e instanceof Error); console.log(typeof e);}JavaScript erlaubt das Werfen beliebiger Werte. Hier ist e instanceof Error false und typeof e ist "string". Das kann Fehlerbehandlungscode zum Absturz bringen, der annimmt, dass alle gefangenen Ausnahmen Error‑Objekte sind. Wirf immer Error‑Instanzen für bessere Debug‑Informationen.
JavaScript erlaubt es, jeden Wert zu werfen, nicht nur Error-Objekte.
Wie lautet der Wert von err.name?
class CustomError extends Error { constructor(message) { super(message); this.name = this.constructor.name; }}const err = new CustomError('test');console.log(err.name);err.name ist "CustomError", weil this.constructor.name den Klassennamen zurückgibt. Das Setzen von this.name = this.constructor.name ist ein gängiges Muster, um sicherzustellen, dass benutzerdefinierte Fehlerklassen den korrekten Namen in Stack‑Traces und Fehlermeldungen anzeigen.
Welchen Wert liefert this.constructor.name für diese Instanz?
Was ist die Ausgabe, wenn name nicht gesetzt wird?
class MyError extends Error { // No constructor or name setting}const err = new MyError('test');console.log(err.name);Wenn this.name nicht explizit gesetzt wird, erbt der Fehler die Standard‑name‑Eigenschaft der Error‑Klasse, die "Error" ist. Deshalb sollten benutzerdefinierte Fehlerklassen immer this.name = this.constructor.name im Konstruktor setzen.
Welchen Standardwert erbt die Eigenschaft name von Error.prototype?
Was gibt wrapper.cause.message zurück?
const original = new Error('Original error');const wrapper = new Error('Wrapper', { cause: original });console.log(wrapper.cause.message);Error.cause (ES2022) ermöglicht das Ketten von Errors, um den ursprünglichen Fehlerkontext zu bewahren. wrapper.cause verweist auf den ursprünglichen Fehler, daher gibt wrapper.cause.message "Original error" zurück. Das ist nützlich, um niedrigere Fehler mit höherem Kontext zu umhüllen.
cause verweist auf den ursprünglichen Fehler. Seine message bleibt unverändert.
Was macht Error.captureStackTrace in V8/Node.js?
function createError(msg) { const err = new Error(msg); Error.captureStackTrace(err, createError); return err;}const error = createError('test');Error.captureStackTrace (V8/Node.js) entfernt die angegebene Funktion (createError) aus dem Stack‑Trace, sodass Fehler‑Factory‑Funktionen für End‑Benutzer unsichtbar werden. Das erzeugt sauberere Stack‑Traces, die auf die Aufrufstelle der Factory zeigen, nicht auf die Factory selbst.
Diese V8-Funktion kann Hilfsfunktionen aus dem Stack-Trace ausblenden.
Wie lautet die Fehlermeldung?
function validate(value) { if (!value) { throw new Error( `Value ${value} is invalid` ); }}try { validate(undefined);} catch (e) { console.log(e.message);}Template-Literale wandeln undefined beim Einsetzen in den String "undefined" um. Die Fehlermeldung wird zu "Value undefined is invalid". Für sauberere Meldungen solltest du value ?? 'null' oder ähnliche Prüfungen vor der Interpolation verwenden.
Wie wird undefined bei der Interpolation eines Template-Literals in Text umgewandelt?
Was wird an den Client gesendet?
// Express.js routeapp.get('/api/data', (req, res) => { const error = new Error('Database failed'); res.json({ error });});res.json() verwendet intern JSON.stringify(), sodass das Error‑Objekt zu {} wird. Der Client erhält {"error":{}}. Um das zu beheben, benutze res.json({ error: error.message }) oder res.json({ error: { message: error.message, name: error.name } }).
Welche Error-Eigenschaften berücksichtigt JSON.stringify?
Was kann Promise.reject() akzeptieren?
Promise.reject('string').catch(e => console.log(typeof e));Promise.reject({code: 404}).catch(e => console.log(e.code));Promise.reject(42).catch(e => console.log(e));Wie throw akzeptiert Promise.reject() jeden beliebigen Wert – Strings, Objekte, Zahlen usw. Das gibt "string", 404 und 42 aus. Prüfe immer den Typ der abgefangenen Werte in Promise‑Ketten, besonders wenn du mit Drittanbieter‑Code arbeitest, der mit Nicht‑Error‑Werten ablehnen könnte.
Wie throw kann auch Promise.reject beliebige Werte verwenden.
Wie zuverlässig sind error.code und error.errno?
const fs = require('fs');fs.readFile('missing.txt', (err, data) => { if (err) { console.log(err.code); // 'ENOENT' console.log(err.errno); // -2 }});Eigenschaften wie code und errno sind umgebungsspezifisch (hier Node.js) und gehören nicht zum standardmäßigen Error‑Objekt. Browser‑Fehler besitzen diese Eigenschaften nicht. Prüfe immer, ob sie existieren: if (err.code === 'ENOENT') anstatt anzunehmen, dass sie vorhanden sind.
code und errno sind keine universellen Eigenschaften jedes JavaScript-Fehlers.
Was geben diese Prüfungen zurück?
const fakeError = { name: 'Error', message: 'Fake error', stack: 'fake stack'};
console.log(fakeError instanceof Error);console.log(Object.prototype.toString.call( fakeError) === '[object Error]');Für dieses gewöhnliche Objekt liefern beide Vergleiche false: Es erbt nicht von Error.prototype, und Object.prototype.toString.call(fakeError) ergibt [object Object]. Ein Objekt kann jedoch über Symbol.toStringTag einen anderen Tag vortäuschen. Diese Prüfungen sind kein Echtheitsnachweis für fremde Werte.
Die eine Prüfung folgt der Prototypkette; die andere liefert einen Objekttag, den Symbol.toStringTag beeinflussen kann.
Beherrsche die Kunst der Fehlerbehandlung
Von Serialisierungs-Fallen bis zu instanceof‑Problemen über Kontextgrenzen – diese fortgeschrittenen Konzepte trennen Junior‑Entwickler von erfahrenen Profis.
Bereit für weitere Herausforderungen? Sieh dir unsere komplette Quiz‑Sammlung für zusätzliche Denksportaufgaben zu JavaScript, Algorithmen und mehr an!
