Was sind Reflexion und Introspektion in JavaScript und warum brauchen Sie sie?
\n\nStellen Sie sich vor, Sie sind ein Programmier-Detektiv. Sie haben ein Objekt, aber Sie wissen nicht, was darin steckt. Welche Eigenschaften hat es? Welcher Natur ist es überhaupt – ein Array, eine Funktion oder nur ein Datensatz? Im normalen Leben schauen wir einfach auf den Code, aber in der dynamischen Welt von JavaScript muss Ihr Programm dies selbst tun können. Das sind Reflexion und Introspektion.
\n\nDiese Begriffe klingen nach Philosophie, aber in Wirklichkeit sind es mächtige Werkzeuge. Introspektion bedeutet, dass der Code sich selbst betrachtet: den Typ einer Variablen prüft, den Namen einer Funktion ermittelt oder die Eigenschaften eines Objekts auflistet. Reflexion geht weiter – es ist die Fähigkeit des Codes, sich selbst zur Laufzeit zu verändern: neue Methoden hinzuzufügen, Prototypen zu ändern oder sogar Proxy-Objekte zu erstellen.
\n\nAuf den ersten Blick mag es scheinen, dass dies nur für Autoren komplexer Frameworks nötig ist. Aber tatsächlich nutzen Sie jeden Tag Introspektion, ohne es zu merken. Wenn Sie typeof x === 'string' schreiben – betreiben Sie bereits Introspektion. Und wenn Sie Object.assign zum Kopieren von Eigenschaften verwenden – wenden Sie Reflexion an.
In diesem Artikel werden wir alle wichtigen Methoden und Techniken durchgehen. Sie erfahren, wie Sie in jedes Objekt „hineinschauen“, wie Sie sicher mit unbekannten Daten arbeiten und wie Sie flexibleren und anpassungsfähigeren Code schreiben. Los geht's!
\n\nGrundlagen der Introspektion: Schauen, was wir in der Hand haben
\n\nIntrospektion beginnt mit einer einfachen Frage: „Was ist das?“. In JavaScript gibt es mehrere eingebaute Operatoren und Methoden, die helfen, diese Frage zu beantworten.
\n\nDer typeof-Operator: schnelle Typprüfung
\n\nDies ist Ihr erster Helfer. typeof gibt einen String zurück, der den Typ des Operanden angibt. Er ist einfach, hat aber ein paar Fallstricke.
console.log(typeof 42); // "number"\nconsole.log(typeof 'hallo'); // "string"\nconsole.log(typeof true); // "boolean"\nconsole.log(typeof undefined); // "undefined"\nconsole.log(typeof null); // "object" — hier ist er, der berühmte Bug!\nconsole.log(typeof []); // "object" — das ist kein Bug, sondern ein Feature\nconsole.log(typeof function(){}); // "function"\n\nBeachten Sie: typeof null gibt "object" zurück. Dies ist ein historischer Fehler von JavaScript, der nicht mehr behoben wird. typeof [] gibt ebenfalls "object" zurück, was logisch ist, da ein Array eine Unterart des Objekts ist. Aber wie unterscheidet man dann ein Array von einem normalen Objekt? Dafür gibt es andere Werkzeuge.
Nützlicher Lifehack: typeof eignet sich perfekt, um zu prüfen, ob eine Variable definiert ist, ohne das Risiko, eine ReferenceError-Ausnahme auszulösen.
if (typeof someGlobalVar !== 'undefined') {\n // someGlobalVar sicher verwenden\n}\n\ninstanceof: Prüfung der Prototypenkette
\n\nWenn typeof die Frage „Welcher primitive Typ?“ beantwortet, dann beantwortet instanceof die Frage „Ist es ein Objekt einer bestimmten Klasse?“. Es prüft, ob der Prototyp des Konstruktors in der Prototypenkette des Objekts vorhanden ist.
const arr = [1, 2, 3];\nconsole.log(arr instanceof Array); // true\nconsole.log(arr instanceof Object); // true — weil Array von Object erbt\n\nconst date = new Date();\nconsole.log(date instanceof Date); // true\nconsole.log(date instanceof Object); // true\n\n// Bei Primitiven funktioniert es nicht\nconsole.log('hallo' instanceof String); // false — Primitiv ist kein Objekt\n\nWichtige Nuance: instanceof kann bei der Arbeit mit iframes oder verschiedenen Ausführungskontexten (z. B. in Node.js) versagen. Jeder Kontext hat sein eigenes globales Objekt, und [] instanceof window.Array könnte false zurückgeben, wenn das Array in einem anderen Frame erstellt wurde. Für solche Fälle verwenden Sie besser Array.isArray().