Symbol.unscopables
Die statische Dateneigenschaft Symbol.unscopables
repräsentiert das wohlbekannte Symbol Symbol.unscopables
. Die with
-Anweisung sucht dieses Symbol im Gültigkeitsbereichsobjekt nach einer Eigenschaft, die eine Sammlung von Eigenschaften enthält, die innerhalb der with
-Umgebung keine Bindungen werden sollen.
Probieren Sie es aus
const object1 = {
property1: 42,
};
object1[Symbol.unscopables] = {
property1: true,
};
with (object1) {
console.log(property1);
// Expected output: Error: property1 is not defined
}
Wert
Das wohlbekannte Symbol Symbol.unscopables
.
Eigenschaften von Symbol.unscopables | |
---|---|
Schreibbar | nein |
Aufzählbar | nein |
Konfigurierbar | nein |
Beschreibung
Das [Symbol.unscopables]
-Symbol (zugänglich über Symbol.unscopables
) kann auf jedem Objekt definiert werden, um Eigenschaftsnamen davon auszuschließen, als lexikalische Variablen in with
-Umgebungsbindungen exponiert zu werden. Beachten Sie, dass bei Verwendung des Strict-Modus with
-Anweisungen nicht verfügbar sind und dieses Symbol wahrscheinlich nicht benötigt wird.
Wenn eine Eigenschaft des [Symbol.unscopables]
-Objekts auf true
(oder einen beliebigen truthy-Wert) gesetzt wird, wird die entsprechende Eigenschaft des with
-Gültigkeitsbereichsobjekts unscopable und daher nicht in den with
-Umfang eingeführt. Wenn eine Eigenschaft auf false
(oder einen beliebigen falsy-Wert) gesetzt wird, wird sie scopable und erscheint somit als lexikalische Gültigkeitsbereichsvariablen.
Bei der Entscheidung, ob x
nicht scopable ist, wird die gesamte Prototypenkette der [Symbol.unscopables]
-Eigenschaft nach einer Eigenschaft namens x
durchsucht. Das bedeutet, dass wenn Sie [Symbol.unscopables]
als einfaches Objekt deklariert haben, auch Object.prototype
-Eigenschaften wie toString
unscopable werden, was zu Rückwärtsinkompatibilitäten für Legacy-Code führen kann, der davon ausgeht, dass diese Eigenschaften normalerweise im Gültigkeitsbereich sind (siehe ein Beispiel unten). Es wird empfohlen, Ihre benutzerdefinierte [Symbol.unscopables]
-Eigenschaft genauso wie Array.prototype[Symbol.unscopables]
mit null
als Prototyp zu versehen.
Dieses Protokoll wird auch von DOM-APIs wie Element.prototype.append()
verwendet.
Beispiele
Scoping in with
-Anweisungen
Der folgende Code funktioniert in ES5 und darunter einwandfrei. Jedoch wurde in ECMAScript 2015 die Methode Array.prototype.values()
eingeführt. Das bedeutet, dass innerhalb einer with
-Umgebung "values" nun die Array.prototype.values()
-Methode wäre und nicht die Variable außerhalb der with
-Anweisung.
var values = [];
with (values) {
// If [Symbol.unscopables] did not exist, values would become
// Array.prototype.values starting with ECMAScript 2015.
// And an error would have occurred.
values.push("something");
}
Der Code, der with (values)
enthält, führte dazu, dass einige Websites in Firefox nicht mehr funktionierten, als Array.prototype.values()
hinzugefügt wurde (Firefox Bug 883914). Außerdem impliziert dies, dass jede zukünftige Hinzufügung von Array-Methoden problematisch sein kann, wenn sie implizit den with
-Gültigkeitsbereich ändert. Daher wurde das [Symbol.unscopables]
-Symbol eingeführt und in Array
als Array.prototype[Symbol.unscopables]
implementiert, um zu verhindern, dass einige der Array-Methoden in die with
-Anweisung einbezogen werden.
Unscopables in Objekten
Sie können [Symbol.unscopables]
auch für Ihre eigenen Objekte festlegen.
const obj = {
foo: 1,
bar: 2,
baz: 3,
};
obj[Symbol.unscopables] = {
// Make the object have `null` prototype to prevent
// `Object.prototype` methods from being unscopable
__proto__: null,
// `foo` will be scopable
foo: false,
// `bar` will be unscopable
bar: true,
// `baz` is omitted; because `undefined` is falsy, it is also scopable (default)
};
with (obj) {
console.log(foo); // 1
console.log(bar); // ReferenceError: bar is not defined
console.log(baz); // 3
}
Vermeidung der Verwendung eines Nicht-Null-Prototyps als [Symbol.unscopables]
Wenn [Symbol.unscopables]
als einfaches Objekt ohne Eliminierung seines Prototyps deklariert wird, können subtile Fehler auftreten. Betrachten Sie den folgenden Code, der vor [Symbol.unscopables]
funktioniert:
const character = {
name: "Yoda",
toString: function () {
return "Use with statements, you must not";
},
};
with (character) {
console.log(name + ' says: "' + toString() + '"'); // Yoda says: "Use with statements, you must not"
}
Um die Rückwärtskompatibilität zu bewahren, entschieden Sie sich, eine [Symbol.unscopables]
-Eigenschaft hinzuzufügen, wenn Sie weitere Eigenschaften zu character
hinzufügen. Möglicherweise tun Sie dies naiv so:
const character = {
name: "Yoda",
toString: function () {
return "Use with statements, you must not";
},
student: "Luke",
[Symbol.unscopables]: {
// Make `student` unscopable
student: true,
},
};
Allerdings funktioniert der obige Code jetzt nicht mehr:
with (character) {
console.log(name + ' says: "' + toString() + '"'); // Yoda says: "[object Undefined]"
}
Dies liegt daran, dass beim Nachschlagen von character[Symbol.unscopables].toString
tatsächlich Object.prototype.toString()
zurückgegeben wird, was ein truthy-Wert ist, wodurch der toString()
-Aufruf in der with()
-Anweisung tatsächlich globalThis.toString()
referenziert — und da dies ohne ein this
aufgerufen wird, ist this
undefined
, wodurch [object Undefined]
zurückgegeben wird.
Selbst wenn die Methode von character
nicht überschrieben wird, wird das Scoping geändert, wenn sie unscopable wird.
const proto = {};
const obj = { __proto__: proto };
with (proto) {
console.log(isPrototypeOf(obj)); // true; `isPrototypeOf` is scoped and `this` is `proto`
}
proto[Symbol.unscopables] = {};
with (proto) {
console.log(isPrototypeOf(obj)); // TypeError: Cannot convert undefined or null to object
// `isPrototypeOf` is unscoped and `this` is undefined
}
Um dies zu beheben, stellen Sie immer sicher, dass [Symbol.unscopables]
nur Eigenschaften enthält, die Sie unscopable machen möchten, ohne Object.prototype
-Eigenschaften.
const character = {
name: "Yoda",
toString: function () {
return "Use with statements, you must not";
},
student: "Luke",
[Symbol.unscopables]: {
// Make the object have `null` prototype to prevent
// `Object.prototype` methods from being unscopable
__proto__: null,
// Make `student` unscopable
student: true,
},
};
Spezifikationen
Specification |
---|
ECMAScript® 2026 Language Specification # sec-symbol.unscopables |