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.
Symbol
ist ein eingebautes Objekt, dessen Konstruktor ein symbol
Primitiv zurückgibt — auch als Symbolwert oder einfach Symbol bezeichnet — das garantiert eindeutig ist. Symbole werden oft verwendet, um Objekten eindeutige Eigenschaftsschlüssel hinzuzufügen, die nicht mit Schlüsseln kollidieren, die anderer Code möglicherweise zu dem Objekt hinzufügt, und die von Mechanismen verborgen 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 Symbol()
-Aufruf garantiert die Rückgabe eines eindeutigen Symbols. Jeder Symbol.for("key")
-Aufruf 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 angegebenen Schlüssel im globalen Symbolregister gefunden werden kann, wird dieses Symbol zurückgegeben. Andernfalls wird ein neues Symbol erstellt, im globalen Symbolregister unter dem angegebenen Schlüssel hinzugefügt und zurückgegeben.
Beschreibung
Um ein neues primitives Symbol zu erstellen, schreiben Sie Symbol()
mit einem optionalen String als Beschreibung:
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 wird jedes Mal ein neues Symbol erstellt:
Symbol("foo") === Symbol("foo"); // false
Die folgende Syntax mit dem new
-Operator wird einen TypeError
auslösen:
const sym = new Symbol(); // TypeError
Dies verhindert, dass Entwickler ein explizites Symbol
-Wrapper-Objekt anstelle eines neuen Symbolwerts erstellen können, und kann überraschend sein, da das Erstellen expliziter Wrapper-Objekte um primitive Datentypen im Allgemeinen 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:
const sym = Symbol("foo");
typeof sym; // "symbol"
const symObj = Object(sym);
typeof symObj; // "object"
Da Symbole der einzige primitive Datentyp mit Referenzidentität sind (das heißt, Sie können dasselbe Symbol nicht zweimal erstellen), verhalten sie sich in gewisser Weise wie Objekte. Zum Beispiel sind sie speicherbereinigbar und können daher in WeakMap
, WeakSet
, WeakRef
, und FinalizationRegistry
-Objekten gespeichert werden.
Geteilte Symbole im globalen Symbolregister
Die obige Syntax mit der Symbol()
-Funktion erstellt ein Symbol, dessen Wert während der gesamten Programmlaufzeit einzigartig bleibt. Um Symbole zu erstellen, die über Dateien und sogar über verschiedene Reiche (von denen jedes seinen eigenen globalen Geltungsbereich hat) verfügbar sind, verwenden Sie die Methoden Symbol.for()
und Symbol.keyFor()
, um Symbole aus dem globalen Symbolregister festzulegen und abzurufen.
Beachten Sie, dass das "globale Symbolregister" nur ein fiktives Konzept ist und möglicherweise keiner internen Datenstruktur in der JavaScript-Engine entspricht – und selbst wenn ein solches Register existiert, ist dessen Inhalt für den JavaScript-Code nicht verfügbar, außer über die Methoden for()
und keyFor()
.
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 dem Symbolwert entsprechenden String-Schlüssel zurückgibt. Jede ist das Inverse der anderen, sodass das Folgende true
ist:
Symbol.keyFor(Symbol.for("tokenString")) === "tokenString"; // true
Da registrierte Symbole willkürlich überall erstellt werden können, verhalten sie sich fast genauso wie die Strings, die sie umhüllen. Daher sind sie nicht garantiert einzigartig und nicht speicherbereinigbar. 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 Reiche hinweg konstant sind. Sie sind als bekannte Symbole bekannt und dienen als "Protokolle" für bestimmte eingebauten JavaScript-Operationen, sodass Benutzer das Verhalten der Sprache anpassen können. Wenn zum Beispiel eine Konstruktorfunktion eine Methode mit Symbol.hasInstance
als Namen hat, wird mit dieser Methode das Verhalten mit dem instanceof
-Operator kodiert.
Vor den bekannten Symbolen 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 Funktion String
wird die toString()
- und valueOf()
-Methoden des Objekts aufrufen. Da jedoch mehr Operationen zur Sprache hinzugefügt werden, kann das Erstellen jeder Operation als "magische Eigenschaft" die Abwärtskompatibilität brechen und das Verhalten der Sprache schwerer nachvollziehbar machen. Bekannte Symbole ermöglichen es, dass die Anpassungen vom 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. Zum Beispiel wurde Symbol.hasInstance
als @@hasInstance
geschrieben, und die Methode Array.prototype[Symbol.iterator]()
würde als Array.prototype[@@iterator]()
bezeichnet werden. Diese Notation wird in der Spezifikation nicht mehr verwendet, aber Sie könnten sie noch in älteren Dokumentationen oder Diskussionen sehen.
Bekannte Symbole haben nicht das Konzept der Speicherbereinigung, da sie in einer festen Anzahl vorkommen und während der gesamten Programmlaufzeit einzigartig sind, ähnlich wie intrinsische Objekte wie Array.prototype
, sodass sie auch in WeakMap
, WeakSet
, WeakRef
, und FinalizationRegistry
-Objekten erlaubt sind.
Symbol-Eigenschaften auf Objekten finden
Die Methode Object.getOwnPropertySymbols()
gibt ein Array von Symbolen zurück und ermöglicht es Ihnen, Symbol-Eigenschaften auf einem bestimmten Objekt zu finden. Beachten Sie, dass jedes Objekt mit keinen eigenen Symbol-Eigenschaften initialisiert wird, sodass dieses Array leer bleibt, es sei denn, Sie haben dem Objekt Symbol-Eigenschaften zugewiesen.
Konstruktor
Symbol()
-
Gibt primitive Werte des Typs Symbol zurück. Löst einen Fehler aus, wenn mit
new
aufgerufen.
Statische Eigenschaften
Die statischen Eigenschaften sind alle bekannte Symbole. In den Beschreibungen dieser Symbole werden wir Formulierungen verwenden wie "Symbol.hasInstance
ist eine Methode, die bestimmt…", beachten Sie jedoch, dass dies sich auf die Semantik einer Methode eines Objekts bezieht, das dieses Symbol als Methodennamen hat (da bekannte Symbole als "Protokolle" fungieren), nicht auf den Wert des Symbols selbst.
Symbol.asyncIterator
-
Eine Methode, die den Standard-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 Instanz erkennt. Wird von
instanceof
verwendet. Symbol.isConcatSpreadable
-
Ein Boolean-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 Standard-Iterator für ein Objekt zurückgibt. Wird von
for...of
verwendet. Symbol.match
-
Eine Methode, die gegen einen String verwendet wird, auch 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 Konstruktionsfunktion, die verwendet wird, um abgeleitete Objekte zu erstellen.
Symbol.split
-
Eine Methode, die einen String an den Indizes aufteilt, 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 zugeordneten Objekts ausgeschlossen sind.
Statische Methoden
Symbol.for()
-
Sucht nach vorhandenen registrierten Symbolen im globalen Symbolregister mit dem gegebenen
Schlüssel
und gibt es zurück, wenn es gefunden wird. Andernfalls wird ein neues Symbol erstellt und mitSchlüssel
registriert. Symbol.keyFor()
-
Ruft einen gemeinsamen Symbolschlüssel aus dem globalen Symbolregister für das gegebene Symbol ab.
Instanzeigenschaften
Diese Eigenschaften sind auf Symbol.prototype
definiert und werden von allen Symbol
-Instanzen geteilt.
Symbol.prototype.constructor
-
Die Konstruktionsfunktion, die das Instanzobjekt erstellt hat. Für
Symbol
-Instanzen ist der anfängliche Wert derSymbol
-Konstruktor. Symbol.prototype.description
-
Ein schreibgeschützter String, der die Beschreibung des Symbols enthält.
Symbol.prototype[Symbol.toStringTag]
-
Der anfängliche Wert der
[Symbol.toStringTag]
-Eigenschaft ist der String"Symbol"
. Diese Eigenschaft wird inObject.prototype.toString()
verwendet. DaSymbol
jedoch auch seine eigenetoString()
-Methode hat, wird diese Eigenschaft nicht verwendet, es sei denn, Sie rufenObject.prototype.toString.call()
mit einem Symbol alsthisArg
auf.
Instanzmethoden
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.
typeof Symbol() === "symbol";
typeof Symbol("foo") === "symbol";
typeof Symbol.iterator === "symbol";
Symbol-Typumwandlungen
Einige Dinge zu beachten, wenn Sie mit der Typumwandlung von Symbolen arbeiten.
- Wenn Sie versuchen, ein Symbol in eine Zahl umzuwandeln, wird ein
TypeError
ausgelöst (z. B.+sym
odersym | 0
). - Bei Verwendung der losen Gleichheit gibt
Object(sym) == sym
true
zurück. Symbol("foo") + "bar"
löst einenTypeError
aus (kann Symbol nicht in String umwandeln). Dies verhindert, dass Sie beispielsweise unbemerkt einen neuen String-Eigenschaftsnamen aus einem Symbol erstellen.- Die "sicherere"
String(sym)
-Umwandlung funktioniert wie ein Aufruf vonSymbol.prototype.toString()
mit Symbolen, aber beachten Sie, dassnew String(sym)
einen Fehler auslöst.
Symbole und for...in Iteration
Symbole sind in for...in
-Iterationen nicht aufzählbar. Außerdem wird Object.getOwnPropertyNames()
keine Symbolobjekteigenschaften zurückgeben, jedoch können Sie Object.getOwnPropertySymbols()
verwenden, um diese zu erhalten.
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-gekoppelte Eigenschaften werden beim Verwenden von JSON.stringify()
vollständig ignoriert:
JSON.stringify({ [Symbol("foo")]: "foo" });
// '{}'
Für weitere Details siehe JSON.stringify()
.
Symbol-Wrapper-Objekte als Eigenschaftsschlüssel
Wenn ein Symbol-Wrapper-Objekt als Eigenschaftsschlüssel verwendet wird, wird dieses Objekt zu seinem umschlossenen Symbol umgewandelt:
const sym = Symbol("foo");
const obj = { [sym]: 1 };
obj[sym]; // 1
obj[Object(sym)]; // still 1
Spezifikationen
Specification |
---|
ECMAScript Language Specification # sec-symbol-objects |
Browser-Kompatibilität
BCD tables only load in the browser
Siehe auch
- Polyfill von
Symbol
incore-js
typeof
- JavaScript-Datentypen und Datenstrukturen
- ES6 In Depth: Symbols auf hacks.mozilla.org (2015)