Symbol

Baseline Widely available *

This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2015.

* Some parts of this feature may have varying levels of support.

Symbol ist ein eingebautes Objekt, dessen Konstruktor einen symbol primitive zurückgibt – auch als Symbolwert oder einfach nur Symbol bezeichnet –, das garantiert einzigartig ist. Symbole werden häufig verwendet, um einzigartigen Eigenschaftsschlüsseln zu einem Objekt hinzuzufügen, die nicht mit Schlüsseln kollidieren, die anderer Code möglicherweise dem Objekt hinzufügt, und die vor jeglichen Mechanismen versteckt sind, die anderer Code typischerweise verwendet, um auf das Objekt zuzugreifen. Dies ermöglicht eine Form der schwachen Kapselung oder eine schwache Form der Informationsverbergung.

Jeder Aufruf von Symbol() garantiert die Rückgabe eines einzigartigen Symbols. Jeder Aufruf von Symbol.for("key") wird immer das gleiche Symbol für einen gegebenen Wert von "key" zurückgeben. Wenn Symbol.for("key") aufgerufen wird und ein Symbol mit dem gegebenen Schlüssel im globalen Symbolregister gefunden werden kann, wird dieses Symbol zurückgegeben. Andernfalls wird ein neues Symbol erstellt, im globalen Symbolregister unter dem gegebenen Schlüssel hinzugefügt und zurückgegeben.

Beschreibung

Um ein neues primitives Symbol zu erstellen, schreibt man Symbol() mit einem optionalen String als Beschreibung:

js
const sym1 = Symbol();
const sym2 = Symbol("foo");
const sym3 = Symbol("foo");

Der obige Code erstellt drei neue Symbole. Beachten Sie, dass Symbol("foo") den String "foo" nicht in ein Symbol umwandelt. Es erstellt jedes Mal ein neues Symbol:

js
Symbol("foo") === Symbol("foo"); // false

Die folgende Syntax mit dem new-Operator wirft einen TypeError:

js
const sym = new Symbol(); // TypeError

Dies verhindert, dass Autoren ein explizites Symbol-Wrapper-Objekt statt eines neuen Symbolwerts erstellen, was überraschen könnte, da das Erstellen expliziter Wrapper-Objekte um primitive Datentypen allgemein möglich ist (zum Beispiel new Boolean, new String und new Number).

Wenn Sie wirklich ein Symbol-Wrapper-Objekt erstellen möchten, können Sie die Object()-Funktion verwenden:

js
const sym = Symbol("foo");
typeof sym; // "symbol"
const symObj = Object(sym);
typeof symObj; // "object"

Da Symbole der einzige primitive Datentyp sind, der eine Referenzidentität hat (das heißt, Sie können das gleiche Symbol nicht zweimal erstellen), verhalten sie sich in gewisser Weise wie Objekte. Zum Beispiel sind sie speicherbereinigt und können daher in WeakMap, WeakSet, WeakRef und FinalizationRegistry-Objekten gespeichert werden.

Geteilte Symbole im globalen Symbolregister

Die obige Syntax unter Verwendung der Symbol()-Funktion erstellt ein Symbol, dessen Wert während der gesamten Lebensdauer des Programms einzigartig bleibt. Um Symbole zu erstellen, die über Dateien hinweg und sogar über verschiedene Bereiche (von denen jeder seinen eigenen globalen Gültigkeitsbereich hat) verfügbar sind, verwenden Sie die Methoden Symbol.for() und Symbol.keyFor(), um Symbole im globalen Symbolregister zu setzen und abzurufen.

Beachten Sie, dass das "globale Symbolregister" nur ein fiktives Konzept ist und nicht mit irgendeiner internen Datenstruktur in der JavaScript-Engine übereinstimmen muss – und selbst wenn ein solches Register existiert, ist sein Inhalt JavaScript-Code nicht zugänglich, außer durch die for()- und keyFor()-Methoden.

Die Methode Symbol.for(tokenString) nimmt einen String-Schlüssel und gibt einen Symbolwert aus dem Register zurück, während Symbol.keyFor(symbolValue) einen Symbolwert nimmt und den entsprechenden String-Schlüssel zurückgibt. Jede Methode ist das Inverse der anderen, sodass Folgendes true ist:

js
Symbol.keyFor(Symbol.for("tokenString")) === "tokenString"; // true

Da registrierte Symbole an beliebiger Stelle beliebig erstellt werden können, verhalten sie sich fast genau wie die Strings, die sie umschließen. Daher sind sie nicht garantiert einzigartig und nicht speicherbereinigt. Daher sind registrierte Symbole in WeakMap, WeakSet, WeakRef und FinalizationRegistry-Objekten nicht erlaubt.

Bekannte Symbole

Alle statischen Eigenschaften des Symbol-Konstruktors sind selbst Symbole, deren Werte über Bereiche hinweg konstant sind. Sie sind als bekannte Symbole bekannt und sollen als "Protokolle" für bestimmte eingebaute JavaScript-Operationen dienen, die es Benutzern ermöglichen, das Verhalten der Sprache anzupassen. Wenn zum Beispiel eine Konstruktorfunktion eine Methode mit Symbol.hasInstance als Name hat, kodiert diese Methode ihr Verhalten mit dem instanceof-Operator.

Vor der Einführung bekannter Symbole verwendete JavaScript normale Eigenschaften, um bestimmte eingebaute Operationen zu implementieren. Zum Beispiel wird die Funktion JSON.stringify versuchen, die toJSON()-Methode jedes Objekts aufzurufen, und die String-Funktion wird die toString()- und valueOf()-Methoden des Objekts aufrufen. Da jedoch immer mehr Operationen zur Sprache hinzugefügt werden, könnte die Zuweisung jeder Operation eine "magische Eigenschaft" darstellen, sodass die Rückwärtskompatibilität bricht und das Verhalten der Sprache schwieriger nachvollziehbar wird. Bekannte Symbole ermöglichen es, dass die Anpassungen für normalen Code "unsichtbar" sind, der typischerweise nur String-Eigenschaften liest.

Hinweis: Die Spezifikation verwendete früher die Notation @@<symbol-name>, um bekannte Symbole zu kennzeichnen. Beispielsweise wurde Symbol.hasInstance als @@hasInstance geschrieben und die Array.prototype[Symbol.iterator]()-Methode würde als Array.prototype[@@iterator]() bezeichnet werden. Diese Notation wird in der Spezifikation nicht mehr verwendet, aber Sie können sie dennoch in älterer Dokumentation oder Diskussionen sehen.

Bekannte Symbole haben kein Konzept der Speicherbereinigbarkeit, da sie in einer festen Menge vorkommen und während der gesamten Lebensdauer des Programms einzigartig sind, ähnlich wie intrinsische Objekte wie Array.prototype, sodass sie auch in WeakMap, WeakSet, WeakRef und FinalizationRegistry-Objekten erlaubt sind.

Finden von Symboleigenschaften auf Objekten

Die Methode Object.getOwnPropertySymbols() gibt ein Array von Symbolen zurück und ermöglicht es Ihnen, Symboleigenschaften auf einem gegebenen Objekt zu finden. Beachten Sie, dass jedes Objekt mit keinen eigenen Symboleigenschaften initialisiert wird, sodass dieses Array leer sein wird, es sei denn, Sie haben Symboleigenschaften auf dem Objekt gesetzt.

Konstruktor

Symbol()

Gibt primitive Werte des Typs Symbol zurück. Wirft einen Fehler, wenn mit new aufgerufen.

Statische Eigenschaften

Die statischen Eigenschaften sind allesamt bekannte Symbole. In den Beschreibungen dieser Symbole werden wir Formulierungen wie „Symbol.hasInstance ist eine Methode, die bestimmt...“ verwenden, aber bedenken Sie, dass damit die Semantik einer Objektmethode gemeint ist, die dieses Symbol als Methodennamen hat (weil bekannte Symbole als „Protokolle“ fungieren), nicht der Wert des Symbols selbst.

Symbol.asyncIterator

Eine Methode, die den standardmäßigen AsyncIterator für ein Objekt zurückgibt. Wird von for await...of verwendet.

Symbol.hasInstance

Eine Methode, die bestimmt, ob ein Konstruktorobjekt ein Objekt als seine Instanz erkennt. Wird von instanceof verwendet.

Symbol.isConcatSpreadable

Ein Boolescher Wert, der angibt, ob ein Objekt auf seine Array-Elemente abgeflacht werden soll. Wird von Array.prototype.concat() verwendet.

Symbol.iterator

Eine Methode, die den standardmäßigen Iterator für ein Objekt zurückgibt. Wird von for...of verwendet.

Symbol.match

Eine Methode, die gegen einen String abgleicht und auch verwendet wird, um zu bestimmen, ob ein Objekt als regulärer Ausdruck verwendet werden kann. Wird von String.prototype.match() verwendet.

Symbol.matchAll

Eine Methode, die einen Iterator zurückgibt, der Übereinstimmungen des regulären Ausdrucks gegen einen String liefert. Wird von String.prototype.matchAll() verwendet.

Symbol.replace

Eine Methode, die übereinstimmende Teilstrings eines Strings ersetzt. Wird von String.prototype.replace() verwendet.

Symbol.search

Eine Methode, die den Index innerhalb eines Strings zurückgibt, der dem regulären Ausdruck entspricht. Wird von String.prototype.search() verwendet.

Symbol.species

Eine Konstruktorfunktion, die verwendet wird, um abgeleitete Objekte zu erstellen.

Symbol.split

Eine Methode, die einen String an den Indizes trennt, die einem regulären Ausdruck entsprechen. Wird von String.prototype.split() verwendet.

Symbol.toPrimitive

Eine Methode, die ein Objekt in einen primitiven Wert umwandelt.

Symbol.toStringTag

Ein String-Wert, der für die Standardbeschreibung eines Objekts verwendet wird. Wird von Object.prototype.toString() verwendet.

Symbol.unscopables

Ein Objektwert, dessen eigene und geerbte Eigenschaftsnamen von den with-Umgebungsbindungen des zugehörigen Objekts ausgeschlossen sind.

Statische Methoden

Symbol.for()

Sucht nach vorhandenen registrierten Symbolen im globalen Symbolregister mit dem gegebenen key und gibt es zurück, wenn es gefunden wird. Andernfalls wird ein neues Symbol erstellt und mit key registriert.

Symbol.keyFor()

Ruft einen gemeinsamen Symbolschlüssel aus dem globalen Symbolregister für das gegebene Symbol ab.

Instanz-Eigenschaften

Diese Eigenschaften sind auf Symbol.prototype definiert und werden von allen Symbol-Instanzen geteilt.

Symbol.prototype.constructor

Die Konstruktorfunktion, die das Instanzobjekt erstellt hat. Für Symbol-Instanzen ist der Anfangswert der Symbol-Konstruktor.

Symbol.prototype.description

Ein schreibgeschützter String, der die Beschreibung des Symbols enthält.

Symbol.prototype[Symbol.toStringTag]

Der Anfangswert der [Symbol.toStringTag]-Eigenschaft ist der String "Symbol". Diese Eigenschaft wird in Object.prototype.toString() verwendet. Da Symbol jedoch auch über seine eigene toString()-Methode verfügt, wird diese Eigenschaft nicht verwendet, es sei denn, Sie rufen Object.prototype.toString.call() mit einem Symbol als thisArg auf.

Instanz-Methoden

Symbol.prototype.toString()

Gibt einen String zurück, der die Beschreibung des Symbols enthält. Überschreibt die Object.prototype.toString()-Methode.

Symbol.prototype.valueOf()

Gibt das Symbol zurück. Überschreibt die Object.prototype.valueOf()-Methode.

Symbol.prototype[Symbol.toPrimitive]()

Gibt das Symbol zurück.

Beispiele

Verwendung des typeof-Operators mit Symbolen

Der typeof-Operator kann Ihnen helfen, Symbole zu identifizieren.

js
typeof Symbol() === "symbol";
typeof Symbol("foo") === "symbol";
typeof Symbol.iterator === "symbol";

Symbol-Typ-Konvertierungen

Einige Punkte, die beim Arbeiten mit der Typkonvertierung von Symbolen zu beachten sind.

  • Beim Versuch, ein Symbol in eine Zahl zu konvertieren, wird ein TypeError geworfen (z.B. +sym oder sym | 0).
  • Beim Verwenden von losem Gleichnis ergibt Object(sym) == sym true.
  • Symbol("foo") + "bar" wirft ein TypeError (kann Symbol nicht in String konvertieren). Dies verhindert, dass Sie stillschweigend einen neuen Eigenschaftsnamen für einen String aus einem Symbol erstellen, zum Beispiel.
  • Die "sichere" String(sym)-Konvertierung funktioniert wie ein Aufruf von Symbol.prototype.toString() bei Symbolen, aber beachten Sie, dass new String(sym) einen Fehler werfen wird.

Symbole und for...in-Iterationen

Symbole sind in for...in-Iterationen nicht aufzählbar. Darüber hinaus wird Object.getOwnPropertyNames() keine Symbol-Objekteigenschaften zurückgeben, aber Sie können Object.getOwnPropertySymbols() verwenden, um diese zu erhalten.

js
const obj = {};

obj[Symbol("a")] = "a";
obj[Symbol.for("b")] = "b";
obj["c"] = "c";
obj.d = "d";

for (const i in obj) {
  console.log(i);
}
// "c" "d"

Symbole und JSON.stringify()

Symbol-schlüsselwerte Eigenschaften werden bei der Verwendung von JSON.stringify() vollständig ignoriert:

js
JSON.stringify({ [Symbol("foo")]: "foo" });
// '{}'

Für weitere Einzelheiten siehe JSON.stringify().

Symbol-Wrapper-Objekte als Eigenschaftsschlüssel

Wenn ein Symbol-Wrapper-Objekt als Eigenschaftsschlüssel verwendet wird, wird dieses Objekt auf sein enthaltenes Symbol geleitet:

js
const sym = Symbol("foo");
const obj = { [sym]: 1 };
obj[sym]; // 1
obj[Object(sym)]; // still 1

Spezifikationen

Specification
ECMAScript® 2025 Language Specification
# sec-symbol-objects

Browser-Kompatibilität

Siehe auch