Start · Sprachen · JavaScript · Referenz · Object.preventExtensions()

Object.preventExtensions()

Methode

Macht ein Objekt nicht erweiterbar: Neue Eigenschaften lassen sich danach nicht mehr hinzufügen, bestehende bleiben änderbar und löschbar.

seit JavaScript ES5 (ES2015: Nicht-Objekte werden ohne TypeError a Kategorie: method-property

Signatur

Object.preventExtensions(obj)

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 Eigenschaften
  • Object.seal(): zusätzlich lässt sich keine Eigenschaft mehr löschen oder neu konfigurieren
  • Object.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

Typ
any
Beschreibung
Dasselbe Objekt (keine Kopie), jetzt nicht erweiterbar. Bei primitiven Werten kommt der übergebene Wert zurück.

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));
{ name: 'Anne' } false

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}`);
}
TypeError: Cannot add property timout, object is not extensible

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 }));
true #<Object> is not extensible false

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'));
Hallo false

// 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 (push wirft immer einen TypeError). Verkürzen über length oder pop() 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 ein TypeError.
  • Kompatibilität: wird von allen modernen Browsern und Node.js unterstützt (Baseline).