Start · Sprachen · JavaScript · Referenz · Symbol.unscopables

Symbol.unscopables

Eigenschaft

Wohlbekanntes Symbol für ein Objekt, dessen Eigenschaftsnamen innerhalb einer <code>with</code>-Anweisung nicht als Variablen gebunden werden.

seit JavaScript ES2015 (Baseline: alle modernen Browser, Node.js 0 Kategorie: method-property

Signatur

Symbol.unscopables

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

Typ
symbol
Beschreibung
Das eindeutige, wohlbekannte Symbol 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));
null true true ["at", "copyWithin", "entries", "fill", "find", "findIndex", "findLast", "findLastIndex", "flat", "flatMap", "includes", "keys", "toReversed", "toSorted", "toSpliced", "values"]

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();
3 äußere Variable

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();
Dashboard false true

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"));
true false

// Wichtig · Fallstricke

  • Nur mit with wirksam: Symbol.unscopables wirkt sich ausschließlich auf with-Anweisungen aus. Die sind im Strict Mode, in ES-Modulen und in Klassen verboten (SyntaxError). Normaler Zugriff wie obj.prop oder obj[\"prop\"] bleibt unverändert.
  • Nur truthy Werte zählen: Hat ein Eintrag den Wert false, 0 oder undefined, bleibt die Eigenschaft im with-Scope sichtbar. Mit false kö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 mit Object.create(null) oder einem Literal mit __proto__: null. Sonst könnten Namen aus Object.prototype ungewollt eine Rolle spielen.
  • Nicht veränderbar: Die statische Eigenschaft Symbol.unscopables ist 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. toSorted in ES2023). Die genaue Ausgabe von Object.keys() hängt also von der Engine-Version ab.
  • Performance und Wartbarkeit: with verhindert viele Optimierungen der Engine und macht Code schwer nachvollziehbar. In neuem Code verwenden Sie besser Destrukturierung wie const { a, b } = obj;.