Signatur
Beschreibung
Symbol.unscopables ist ein wohlbekanntes Symbol (well-known symbol). Legt ein Objekt unter diesem Schlüssel eine Eigenschaft an, muss deren Wert selbst ein Objekt sein. Jeder Eigenschaftsname, der in diesem Objekt einen truthy Wert hat, wird innerhalb einer with-Anweisung nicht an das Objekt gebunden. Die Namensauflösung sucht dann im äußeren Gültigkeitsbereich weiter.
Der Mechanismus wurde vor allem für die Abwärtskompatibilität eingeführt. Als ES2015 neue Array-Methoden wie keys, values oder entries brachte, hätten sie in altem Code mit with (array) { ... } gleichnamige äußere Variablen verdeckt. Deshalb enthält Array.prototype[Symbol.unscopables] alle neueren Methoden, etwa at, flat, includes, findLast oder toSorted.
In eigenem Code braucht man Symbol.unscopables selten, denn with ist im Strict Mode und damit auch in ES-Modulen und Klassenkörpern verboten. Nützlich ist das Symbol vor allem, wenn Sie Bibliotheken oder Sandbox-Umgebungen bauen, die mit with oder einem Proxy einen eigenen Gültigkeitsbereich nachbilden, etwa Template-Engines. Außerdem hilft es, das Verhalten eingebauter Objekte zu verstehen.
Die Eigenschaft Symbol.unscopables selbst ist nicht beschreibbar, nicht aufzählbar und nicht konfigurierbar.
Rückgabewert
Symbol.unscopables. Es ist in allen Realms (z. B. iframes) identisch.Beispiele
Unscopables von Array.prototype untersuchen
const unscopables = Array.prototype[Symbol.unscopables];
// Das Objekt hat keinen Prototyp, damit geerbte Namen wie "toString" nicht stören
console.log(Object.getPrototypeOf(unscopables));
console.log(unscopables.includes, unscopables.flat);
console.log(Object.keys(unscopables));
Wirkung in einer with-Anweisung (nur im Sloppy Mode)
// Klassisches Skript ohne "use strict", da with sonst ein SyntaxError ist
function demo() {
const keys = "äußere Variable";
const arr = [10, 20, 30];
with (arr) {
console.log(length); // wird an arr gebunden
console.log(keys); // ist unscopable, also die äußere Variable
}
}
demo();
Eigene Eigenschaften aus dem with-Scope ausblenden
function render() {
const debug = false; // globale Einstellung, die gelten soll
const config = {
title: "Dashboard",
debug: true,
[Symbol.unscopables]: { debug: true }
};
with (config) {
console.log(title, debug);
}
console.log(config.debug); // direkter Zugriff funktioniert weiterhin
}
render();
Unscopables in einer Proxy-Sandbox berücksichtigen
const scope = {
user: "Anna",
secret: "geheim",
[Symbol.unscopables]: { secret: true }
};
// Eine Sandbox fragt beim Auflösen von Namen in einem with-Block erst "has" ab
const isVisible = (obj, key) =>
key in obj && !obj[Symbol.unscopables]?.[key];
console.log(isVisible(scope, "user"));
console.log(isVisible(scope, "secret"));
// Wichtig · Fallstricke
- Nur mit
withwirksam:Symbol.unscopableswirkt sich ausschließlich aufwith-Anweisungen aus. Die sind im Strict Mode, in ES-Modulen und in Klassen verboten (SyntaxError). Normaler Zugriff wieobj.propoderobj[\"prop\"]bleibt unverändert. - Nur truthy Werte zählen: Hat ein Eintrag den Wert
false,0oderundefined, bleibt die Eigenschaft imwith-Scope sichtbar. Mitfalsekönnen Sie also geerbte Einträge gezielt wieder freigeben. - Auch geerbte Einträge zählen: Das Unscopables-Objekt wird mit normalem
[[Get]]gelesen, geerbte Eigenschaften wirken also mit. Erstellen Sie es deshalb am besten mitObject.create(null)oder einem Literal mit__proto__: null. Sonst könnten Namen ausObject.prototypeungewollt eine Rolle spielen. - Nicht veränderbar: Die statische Eigenschaft
Symbol.unscopablesist nicht beschreibbar, nicht aufzählbar und nicht konfigurierbar. Veränderbar ist nur das Objekt, das unter diesem Schlüssel auf einem Zielobjekt liegt, z. B.Array.prototype[Symbol.unscopables]. Das zu ändern ist aber nicht zu empfehlen. - Kompatibilität: Wird von allen modernen Browsern und von Node.js unterstützt, nicht aber vom Internet Explorer. Die Liste der Array-Einträge wächst mit neuen ECMAScript-Versionen (z. B.
toSortedin ES2023). Die genaue Ausgabe vonObject.keys()hängt also von der Engine-Version ab. - Performance und Wartbarkeit:
withverhindert viele Optimierungen der Engine und macht Code schwer nachvollziehbar. In neuem Code verwenden Sie besser Destrukturierung wieconst { a, b } = obj;.