Signatur
Beschreibung
Die Eigenschaft __proto__ ist ein Getter/Setter-Paar auf Object.prototype. Der Getter liefert den Prototyp eines Objekts, also das Objekt, von dem es Eigenschaften und Methoden erbt. Der Setter ändert diesen Prototyp nachträglich. Intern entspricht das Lesen Object.getPrototypeOf(this) und das Schreiben Object.setPrototypeOf(this, wert).
Ursprünglich eine nicht standardisierte Browser-Erweiterung, wurde __proto__ in ES2015 nur aus Kompatibilitätsgründen in Anhang B (Legacy-Features für Webbrowser) aufgenommen. Für neuen Code sollte man stattdessen Object.getPrototypeOf(), Object.setPrototypeOf() und Object.create() verwenden.
Wichtig: Die Accessor-Eigenschaft funktioniert nur bei Objekten, die (direkt oder indirekt) von Object.prototype erben. Objekte mit Object.create(null) besitzen kein __proto__. Davon zu unterscheiden ist die Objektliteral-Syntax { __proto__: proto }: Sie ist regulär standardisiert, nicht veraltet und setzt den Prototyp direkt beim Erzeugen – auch ohne Abhängigkeit von Object.prototype.
Wird dem Setter ein Wert zugewiesen, der weder Objekt noch null ist, passiert stillschweigend nichts. Bei nicht erweiterbaren Objekten (Object.preventExtensions()) oder bei zyklischen Prototyp-Ketten wird ein TypeError geworfen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $value | Object | null | Nur beim Setzen: der neue Prototyp. Andere Werte (z. B. Zahlen, Strings) werden ignoriert, ohne Fehler. |
Rückgabewert
[[Prototype]] des Objekts bzw. null am Ende der Prototyp-Kette. Beim Setzen: undefined (die Zuweisung selbst ergibt den zugewiesenen Wert).Beispiele
Prototyp lesen
class Tier {}
class Hund extends Tier {}
const bello = new Hund();
console.log(bello.__proto__ === Hund.prototype);
console.log(bello.__proto__.__proto__ === Tier.prototype);
console.log(Object.prototype.__proto__);
// Moderne Alternative:
console.log(Object.getPrototypeOf(bello) === Hund.prototype);
Prototyp nachträglich setzen (veraltet) vs. moderne Alternativen
const basis = {
gruss() { return `Hallo, ${this.name}!`; }
};
const nutzer = { name: 'Anna' };
nutzer.__proto__ = basis; // Legacy-Setter
console.log(nutzer.gruss());
// Besser:
const nutzer2 = Object.create(basis, { name: { value: 'Ben' } });
console.log(nutzer2.gruss());
// Objektliteral-Syntax (standardisiert, nicht veraltet):
const nutzer3 = { __proto__: basis, name: 'Cem' };
console.log(nutzer3.gruss());
Objekte ohne Object.prototype
const dict = Object.create(null);
console.log(dict.__proto__); // kein Accessor vorhanden
dict.__proto__ = { x: 1 }; // wird zur normalen Eigenschaft
console.log(Object.keys(dict));
console.log(Object.getPrototypeOf(dict));
Ungültige Werte und Fehlerfälle
const obj = {};
obj.__proto__ = 42; // wird ignoriert
console.log(Object.getPrototypeOf(obj) === Object.prototype);
const a = {};
const b = { __proto__: a };
try {
a.__proto__ = b; // Zyklus
} catch (e) {
console.log(e instanceof TypeError);
}
// Wichtig · Fallstricke
- Veraltet: Der Accessor
Object.prototype.__proto__ist nur als Legacy-Feature (Annex B) standardisiert. Deno und manche gehärteten Umgebungen (z. B. Node.js mit--disable-proto) stellen ihn nicht bereit. NutzeObject.getPrototypeOf()/Object.setPrototypeOf(). - Performance: Das nachträgliche Ändern des Prototyps macht Optimierungen der JavaScript-Engines zunichte und kann Code deutlich verlangsamen – auch Code, der das Objekt später nur liest. Prototyp besser beim Erzeugen festlegen (
Object.create()oder{ __proto__: … }). - Sicherheit – Prototype Pollution: Werden Schlüssel aus unkontrollierten Daten (z. B.
JSON.parse-Ergebnissen, Query-Strings) rekursiv in Objekte gemischt, kann ein Schlüssel"__proto__"Object.prototypemanipulieren und alle Objekte der Anwendung beeinflussen. Gegenmaßnahmen: Schlüssel__proto__,constructorundprototypefiltern,Object.create(null)oderMapals Wörterbuch verwenden, ggf.Object.freeze(Object.prototype). JSON.parse('{"__proto__": {}}')erzeugt eine eigene Eigenschaft namens__proto__, setzt aber keinen Prototyp; erst das anschließende Kopieren per Zuweisung ist gefährlich.- Berechnete Schlüssel (
{ ["__proto__"]: x }) und Kurzschreibweise ({ __proto__ }) setzen im Objektliteral keinen Prototyp, sondern legen eine normale Eigenschaft an.