Signatur
Beschreibung
Die Methode setPrototypeOf() im Handler-Objekt eines Proxy wird immer dann aufgerufen, wenn jemand den Prototyp des Proxys ändern will. Damit kannst du Prototyp-Änderungen protokollieren, prüfen, nur bestimmte Prototypen zulassen oder sie ganz verbieten.
Die Trap fängt folgende Operationen ab:
Object.setPrototypeOf(proxy, proto)Reflect.setPrototypeOf(proxy, proto)- den Setter
proxy.__proto__ = proto(Object.prototype.__proto__)
Die Trap muss einen Wahrheitswert zurückgeben: true heißt, die Änderung war erfolgreich, false heißt, sie ist fehlgeschlagen. Gibt die Trap false zurück, wirft Object.setPrototypeOf() einen TypeError. Reflect.setPrototypeOf() gibt dagegen einfach false zurück. So kannst du dasselbe Verbot sowohl mit Fehler als auch ohne Fehler auswerten.
Wenn du das Standardverhalten beibehalten und nur ergänzen willst, rufst du in der Trap Reflect.setPrototypeOf(target, prototype) auf und gibst dessen Ergebnis zurück.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | object | Das Zielobjekt, das der Proxy umhüllt. | |
| $prototype Pflicht | object | null | Der neue Prototyp, der gesetzt werden soll, oder null. |
Rückgabewert
true, wenn der Prototyp erfolgreich geändert wurde, sonst false. Andere Werte werden in einen Wahrheitswert umgewandelt.Beispiele
Prototyp-Änderungen protokollieren und weiterreichen
const ziel = {};
const proxy = new Proxy(ziel, {
setPrototypeOf(target, proto) {
console.log('Neuer Prototyp:', proto === Array.prototype ? 'Array.prototype' : proto);
return Reflect.setPrototypeOf(target, proto);
}
});
Object.setPrototypeOf(proxy, Array.prototype);
console.log(Object.getPrototypeOf(ziel) === Array.prototype);
Prototyp-Änderung verbieten – mit und ohne Fehler
const gesperrt = new Proxy({}, {
setPrototypeOf() {
return false; // Änderung ablehnen
}
});
// Reflect: kein Fehler, nur false
console.log(Reflect.setPrototypeOf(gesperrt, null));
// Object.setPrototypeOf: wirft TypeError
try {
Object.setPrototypeOf(gesperrt, null);
} catch (err) {
console.log(err instanceof TypeError);
}
Nur bestimmte Prototypen zulassen
class Basis {}
class Erweitert extends Basis {}
const modell = new Proxy(new Basis(), {
setPrototypeOf(target, proto) {
// Nur Prototypen erlauben, die von Basis abstammen
if (proto !== null && Basis.prototype.isPrototypeOf(proto) || proto === Basis.prototype) {
return Reflect.setPrototypeOf(target, proto);
}
return false;
}
});
console.log(Reflect.setPrototypeOf(modell, Erweitert.prototype));
console.log(Reflect.setPrototypeOf(modell, Date.prototype));
console.log(modell instanceof Erweitert);
// Wichtig · Fallstricke
Invariante: Ist das Zielobjekt nicht erweiterbar (Object.preventExtensions(), Object.seal(), Object.freeze()), darf die Trap nur dann true zurückgeben, wenn prototype genau dem aktuellen Prototyp des Ziels entspricht (Object.getPrototypeOf(target)). Gibt sie trotzdem true zurück, wirft die Engine einen TypeError.
Rückgabewert: Gibst du true zurück, ohne den Prototyp wirklich zu ändern, meldet die Operation einen Erfolg, der gar nicht stattgefunden hat. Das führt zu schwer auffindbaren Fehlern. Am sichersten ist es, das Ergebnis von Reflect.setPrototypeOf() zurückzugeben.
Leistung: Engines optimieren Objekte stark anhand ihres Prototyps. Wenn du den Prototyp eines Objekts nachträglich änderst, verlieren viele dieser Optimierungen ihre Wirkung, egal ob mit oder ohne Proxy. Verwende Object.create(), wenn möglich.
Was die Trap nicht abfängt: Object.create() und die class … extends-Syntax setzen den Prototyp direkt beim Erzeugen. Sie lösen diese Trap nicht aus. Den Prototyp auslesen, etwa mit Object.getPrototypeOf(), fängt die Trap getPrototypeOf ab.
Kompatibilität: Wird von allen modernen Browsern und Node.js unterstützt. In Internet Explorer gibt es diese Trap nicht, und sie lässt sich auch nicht nachrüsten (Polyfill).