W3docs

JavaScript Prototyp-Methoden ohne __proto__

Erfahren Sie mehr über moderne JavaScript-Prototyp-Methoden wie Object.create(), Object.getPrototypeOf() und Object.setPrototypeOf() sowie sichere Wörterbuch-Objekte ohne Prototyp.

Jedes JavaScript-object ist mit einem anderen object verknüpft, das als sein Prototyp bezeichnet wird, und Property-Suchen wandern diese Kette hinauf. Die alte Methode, diesen Link zu lesen oder zu ändern, war die spezielle __proto__-Property, die jedoch echte Probleme hat: Sie ist ein geerbter Accessor (kein normaler Datenspeicher), verhält sich inkonsistent als object-Schlüssel und kann ausgenutzt werden, um Objekte zu beschädigen. Modernes JavaScript ersetzt sie durch explizite, vorhersehbare Methoden am Object-Konstruktor.

Dieses Kapitel zeigt die standardisierten Prototyp-Methoden — Object.create(), Object.getPrototypeOf() und Object.setPrototypeOf() — sowie die Inspektions-Hilfsfunktionen Object.keys(), Object.values(), Object.entries() und Object.hasOwn(). Anschließend wird der nützlichste Anwendungsfall für ein object ohne Prototyp behandelt: ein sicheres „Wörterbuch" für beliebige Schlüssel.

Einen umfassenden Überblick darüber, wie die Kette funktioniert, finden Sie unter Prototypale Vererbung und mehr.

Einen Prototyp lesen und setzen

Verwenden Sie Object.getPrototypeOf(), um den Prototyp eines object zu lesen, und Object.setPrototypeOf(), um ihn zu ändern. Dies sind die standardisierten Ersatzmethoden für das Lesen und Schreiben von __proto__.

javascript— editable

Object.create(proto) erstellt ein brandneues object, dessen Prototyp genau proto ist. Es ist der sauberste Weg, ein object mit einem gewählten Prototyp zu erstellen, ohne __proto__ überhaupt zu verwenden.

Warum __proto__ vermeiden?

__proto__ ist ein Getter/Setter, der auf Object.prototype definiert ist, keine Property, die auf Ihrem object lebt. Dieser Unterschied verursacht zwei praktische Probleme:

  • Es kann als Datenschlüssel fehlschlagen oder sich seltsam verhalten. Da obj.__proto__ = value den Setter auslöst, kann man unter einem normalen object keinen Schlüssel namens "__proto__" zuverlässig speichern — das Zuweisen eines Nicht-object wird stillschweigend ignoriert, und das Zuweisen eines object ändert den Prototyp, anstatt einen Schlüssel hinzuzufügen.
  • Es ist eine bekannte Angriffsfläche („Prototype Pollution"). Code, der nicht vertrauenswürdige Schlüssel auf ein object kopiert, kann dazu verleitet werden, in __proto__ zu schreiben, wodurch Object.prototype für das gesamte Programm verunreinigt wird.

Die standardisierten Methoden sind in ihrer Absicht eindeutig: getPrototypeOf/setPrototypeOf ändern den Prototyp, während normale Property-Schreibvorgänge ihn niemals berühren.

javascript— editable

Objekte ohne Prototyp

Object.create(null) erstellt ein object, dessen Prototyp null ist. Es erbt nichts — nicht einmal toString, hasOwnProperty oder den __proto__-Accessor.

javascript— editable

Das Wörterbuch-Problem, das es löst

Ein verbreitetes Muster ist die Verwendung eines einfachen object als Zuordnung von string-Schlüsseln zu Werten. Das Problem ist, dass ein einfaches {} bereits Schlüssel von Object.prototype erbt, sodass vom Benutzer gelieferte Schlüssel wie "constructor", "toString" oder "__proto__" mit den geerbten Namen kollidieren und Abfragen zerstören.

javascript— editable

Ein null-Prototyp-object hat keine geerbten Schlüssel, sodass sich jeder Schlüssel genau so verhält, wie er geschrieben wurde — einschließlich "__proto__":

javascript— editable

Deshalb eignen sich null-Prototyp-Objekte als sichere Wörterbücher für nicht vertrauenswürdige Schlüssel. (Die eingebaute Map ist eine weitere gute Wahl und erlaubt auch Nicht-string-Schlüssel.)

Methoden zu einem null-Prototyp-object hinzufügen

Da kein Prototyp zur Verfügung steht, von dem geerbt werden könnte, weisen Sie Methoden direkt als eigene Properties zu.

javascript— editable

Schlüssel, Werte und Einträge iterieren

Object.keys(), Object.values() und Object.entries() geben arrays der eigenen enumerable Properties eines object zurück. Entscheidend ist, dass sie die Prototyp-Kette ignorieren und daher auf normalen und null-Prototyp-Objekten identisch funktionieren. Weitere Informationen finden Sie unter Object.keys, values, entries.

javascript— editable

Ein Vorbehalt bei null-Prototyp-Objekten: Sie haben kein geerbtes toString, sodass das direkte Übergeben an Template Literals oder String() einen Fehler wirft. Verwenden Sie stattdessen die Object.*-Hilfsfunktionen (oben) anstatt auf automatische string-Konvertierung zu vertrauen.

Eigene Properties mit Object.hasOwn() prüfen

Um zu testen, ob ein Schlüssel eine eigene Property des object ist (nicht geerbt), bevorzugen Sie Object.hasOwn(). Es ist der moderne Ersatz für obj.hasOwnProperty() und funktioniert auch bei null-Prototyp-Objekten, die überhaupt keine hasOwnProperty-Methode besitzen.

javascript— editable

Komposition mit Object.assign()

Wenn ein object das Verhalten mehrerer anderer übernehmen soll, ist Komposition oft klarer als eine einzelne Vererbungskette: Ein object kann nur einen Prototyp haben, aber Object.assign(target, ...sources) kann Methoden aus vielen Quellen zusammenführen, indem es deren eigene enumerable Properties auf das Ziel kopiert.

javascript— editable

Object.assign() kopiert auch auf ein null-Prototyp-object und ergibt so ein zusammengesetztes Wörterbuch ohne geerbte Oberfläche:

javascript— editable

Vorbehalt bei flachem Kopieren: Object.assign() kopiert Property-Werte, keine tiefen Klone. object- und array-Werte werden als Referenz kopiert, sodass Quelle und Ziel dieselben verschachtelten Objekte teilen.

javascript— editable

Für eine tiefe, unabhängige Kopie verwenden Sie stattdessen structuredClone(source).

Best Practices

  • Verwenden Sie die standardisierten Methoden, nicht __proto__. Greifen Sie auf Object.create(), Object.getPrototypeOf() und Object.setPrototypeOf() zurück. Behandeln Sie __proto__ als veralteten Accessor, den Sie in eigenem Code vermeiden sollten.
  • Vermeiden Sie das Ändern von Prototypen nach der Erstellung. Einen gewählten Prototyp zum Erstellungszeitpunkt mit Object.create(proto) festzulegen ist sauberer und leichter nachzuvollziehen als ihn später mit Object.setPrototypeOf() zu mutieren.
  • Verwenden Sie Object.create(null) (oder Map) für Wörterbücher mit nicht vertrauenswürdigen Schlüsseln. Dadurch werden geerbte Schlüssel entfernt und Prototype-Pollution-Überraschungen verhindert.
  • Bevorzugen Sie Object.hasOwn() gegenüber obj.hasOwnProperty(). Es ist kürzer, sicherer aufzurufen und funktioniert bei null-Prototyp-Objekten.
  • Komponieren Sie mit Object.assign(), wenn Sie Verhalten aus mehreren Quellen benötigen — denken Sie nur daran, dass es sich um eine flache Kopie handelt.

Verwandtes Material finden Sie unter Objekt-Methoden und „this" und Property-Flags und -Deskriptoren.

Fazit

Die modernen Object.*-Prototyp-Methoden geben Ihnen explizite, vorhersehbare Kontrolle über die Prototyp-Kette und ersetzen den eigenwilligen __proto__-Accessor. Object.create(null) erzeugt ein sauberes, prototyp-freies object, das ideal für Wörterbücher ist, während Object.keys/values/entries, Object.hasOwn() und Object.assign() es Ihnen ermöglichen, Objekte unabhängig von ihrem Prototyp sicher zu inspizieren und zu komponieren.

Übung

Übung
Welcher Aufruf erstellt ein object ohne Prototyp und macht es zu einem sicheren Wörterbuch für beliebige Schlüssel?
Welcher Aufruf erstellt ein object ohne Prototyp und macht es zu einem sicheren Wörterbuch für beliebige Schlüssel?
Was this page helpful?