Signatur
Beschreibung
Die Methode preventExtensions() eines Proxy-Handlers wird immer dann aufgerufen, wenn ein Proxy nicht mehr erweiterbar gemacht werden soll. Mit ihr kannst du diesen Vorgang protokollieren, an Bedingungen knüpfen oder ganz verbieten, zum Beispiel wenn ein Objekt immer erweiterbar bleiben soll.
Ausgelöst wird der Trap durch Object.preventExtensions(proxy), Reflect.preventExtensions(proxy) sowie intern durch Object.seal(proxy) und Object.freeze(proxy).
Der Trap muss einen booleschen Wert liefern: true bedeutet, dass der Vorgang geklappt hat, false bedeutet, dass er gescheitert ist. Bei false wirft Object.preventExtensions() einen TypeError, während Reflect.preventExtensions() einfach false zurückgibt. Nicht-boolesche Rückgabewerte werden in einen Wahrheitswert umgewandelt.
Wichtig ist eine Invariante: Der Trap darf nur dann true zurückgeben, wenn das Zielobjekt danach tatsächlich nicht mehr erweiterbar ist, also Object.isExtensible(target) den Wert false ergibt. Sonst wirft die Engine einen TypeError. Am einfachsten hältst du diese Regel ein, indem du die Arbeit mit Reflect.preventExtensions(target) an das Zielobjekt weitergibst.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | Object | Das Zielobjekt des Proxys. Innerhalb des Traps ist this an das Handler-Objekt gebunden. |
Rückgabewert
true, wenn das Zielobjekt jetzt nicht mehr erweiterbar ist, sonst false. Andere Werte werden in einen Wahrheitswert umgewandelt.Beispiele
Aufrufe protokollieren und an das Ziel weitergeben
const target = { name: 'Config' };
const proxy = new Proxy(target, {
preventExtensions(t) {
console.log('preventExtensions aufgerufen');
return Reflect.preventExtensions(t);
}
});
Object.preventExtensions(proxy);
console.log(Object.isExtensible(proxy));
console.log(Object.isExtensible(target));
Sperren verbieten – Objekt bleibt erweiterbar
const registry = new Proxy({}, {
preventExtensions() {
return false; // Vorgang ablehnen
}
});
console.log(Reflect.preventExtensions(registry));
try {
Object.preventExtensions(registry);
} catch (err) {
console.log(err instanceof TypeError);
}
registry.neu = 1; // funktioniert weiterhin
console.log(registry.neu);
Verstoß gegen die Invariante
const proxy = new Proxy({}, {
preventExtensions() {
return true; // gelogen: Ziel bleibt erweiterbar
}
});
try {
Object.preventExtensions(proxy);
} catch (err) {
console.log(err.name);
}
Auch Object.freeze() löst den Trap aus
const proxy = new Proxy({ a: 1 }, {
preventExtensions(t) {
console.log('Trap ausgelöst');
return Reflect.preventExtensions(t);
}
});
Object.freeze(proxy);
console.log(Object.isFrozen(proxy));
// Wichtig · Fallstricke
- Invariante: Gibt der Trap
truezurück, obwohlObject.isExtensible(target)nochtrueergibt, wirft die Engine einenTypeError. Object.preventExtensions()wirft beifalseeinenTypeError,Reflect.preventExtensions()gibt dagegen nurfalsezurück. Für Code, der mit Fehlschlägen rechnet, istReflectdaher die bessere Wahl.Object.seal()undObject.freeze()lösen den Trap ebenfalls aus. Wenn erfalseliefert, schlagen diese Aufrufe mit einemTypeErrorfehl.- Fehlt der Trap, wird die Operation unverändert an das Zielobjekt weitergegeben.
- Der Trap sollte zum Trap
isExtensiblepassen. Beide müssen den tatsächlichen Zustand des Zielobjekts widerspiegeln. - Kompatibilität: ES2015, in allen modernen Browsern und in Node.js verfügbar. Nicht nachrüstbar (kein Polyfill möglich).