Signatur
Beschreibung
Object.preventExtensions() markiert ein Objekt als nicht erweiterbar. Danach kann man dem Objekt keine neuen eigenen Eigenschaften mehr hinzufügen. Bestehende Eigenschaften lassen sich aber weiterhin ändern (sofern sie beschreibbar sind), neu konfigurieren und mit delete entfernen.
Die Methode ist die schwächste der drei Schutzstufen für Objekte:
Object.preventExtensions(): keine neuen EigenschaftenObject.seal(): zusätzlich lässt sich keine Eigenschaft mehr löschen oder neu konfigurierenObject.freeze(): zusätzlich lassen sich keine Werte mehr ändern
Sinnvoll ist das bei Konfigurations- oder Zustandsobjekten mit festem Aufbau. Tippfehler wie config.timout = 500 legen dann nicht mehr still eine neue Eigenschaft an, sondern werfen im Strict Mode einen TypeError. Außerdem lässt sich der Prototyp eines nicht erweiterbaren Objekts nicht mehr ändern (Object.setPrototypeOf() bzw. __proto__).
Der Vorgang lässt sich nicht rückgängig machen: Ein nicht erweiterbares Objekt wird nie wieder erweiterbar. Ob ein Objekt erweiterbar ist, prüft man mit Object.isExtensible().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $obj Pflicht | any | Das Objekt, das nicht erweiterbar werden soll. Primitive Werte werden seit ES2015 unverändert zurückgegeben, statt einen Fehler zu werfen. |
Rückgabewert
Beispiele
Grundverhalten: Hinzufügen blockiert, Ändern und Löschen erlaubt
const user = { name: 'Anna', role: 'admin' };
Object.preventExtensions(user);
user.email = 'anna@example.com'; // wird im Sloppy Mode still ignoriert
user.name = 'Anne'; // erlaubt
delete user.role; // erlaubt
console.log(user);
console.log(Object.isExtensible(user));
Strict Mode: Tippfehler in der Konfiguration abfangen
'use strict';
const config = Object.preventExtensions({
timeout: 3000,
retries: 3,
});
try {
config.timout = 500; // Tippfehler!
} catch (err) {
console.error(`${err.name}: ${err.message}`);
}
defineProperty und Prototyp-Änderung schlagen fehl
const point = Object.preventExtensions({ x: 1, y: 2 });
try {
Object.defineProperty(point, 'z', { value: 3 });
} catch (err) {
console.log(err instanceof TypeError); // wirft immer, auch ohne Strict Mode
}
try {
Object.setPrototypeOf(point, { foo: 'bar' });
} catch (err) {
console.log(err.message);
}
// Reflect liefert stattdessen einen Wahrheitswert
console.log(Reflect.defineProperty(point, 'z', { value: 3 }));
Neue Eigenschaften über den Prototyp bleiben möglich
const proto = {};
const obj = Object.preventExtensions(Object.create(proto));
proto.greet = () => 'Hallo'; // der Prototyp selbst ist weiterhin erweiterbar
console.log(obj.greet()); // geerbt, keine eigene Eigenschaft
console.log(Object.hasOwn(obj, 'greet'));
// Wichtig · Fallstricke
- Stilles Scheitern: Außerhalb des Strict Mode werden Zuweisungen an neue Eigenschaften ohne Fehlermeldung ignoriert. In ES-Modulen und Klassen gilt automatisch der Strict Mode, dort gibt es einen
TypeError.Object.defineProperty()wirft in beiden Modi. - Nur flach: Verschachtelte Objekte bleiben erweiterbar. Für tiefen Schutz muss man rekursiv vorgehen.
- Nicht umkehrbar: Es gibt keine Methode, die ein Objekt wieder erweiterbar macht. Wenn nötig, legt man mit
{ ...obj }eine erweiterbare Kopie an. - Prototypkette: Der Prototyp wird nicht mitgeschützt. Eigenschaften, die man ihm hinzufügt, sind weiterhin über die Vererbung erreichbar.
- Arrays: Bei einem nicht erweiterbaren Array schlagen
push()und das Zuweisen an neue Indizes fehl (pushwirft immer einenTypeError). Verkürzen überlengthoderpop()geht weiterhin. - ES5 vs. ES2015: In ES5 warf die Übergabe eines primitiven Werts einen
TypeError, seit ES2015 wird der Wert einfach zurückgegeben. - ArrayBuffer-Views: Typisierte Arrays mit veränderbarer Länge (über einen größenänderbaren
ArrayBuffer) lassen sich nicht als nicht erweiterbar markieren. Es entsteht einTypeError. - Kompatibilität: wird von allen modernen Browsern und Node.js unterstützt (Baseline).