Ein Symbolprimitiv stellt einen eindeutigen Wert dar, der nie mit einem anderen Wert kollidiert, einschließlich des Werts anderer Symbolprimitiven. Zwei Stringprimitive, die aus identischen Zeichen bestehen, werden als genau gleich ausgewertet:
String() === String()
> true
String( "My string." ) === String( "My string." );
> true
Es gibt jedoch keine zwei Symbole, die mit der Funktion Symbol()
erstellt wurden und genau gleich sind:
Symbol() === Symbol()
> false
Mit diesem Attribut können Sie Symbole als eindeutige Property-Schlüssel in einem Objekt verwenden, um Kollisionen mit Schlüsseln zu vermeiden, die diesem Objekt möglicherweise durch anderen Code hinzugefügt werden.
const mySymbol = Symbol( "Desc" );
const myObject = {};
myObject[mySymbol] = "propSymbol";
myObject
> Object { Symbol("Desc"): "propSymbol" }
Es gibt drei Arten von Symbolen:
- Mit
Symbol()
erstellte Symbole - Freigegebene Symbole, die mit
Symbol.for()
in einer globalen Symbolregistrierung festgelegt und abgerufen werden - „Gängige Symbole“, die als statische Properties auf dem Symbolobjekt definiert sind. Diese Symbole enthalten interne Methoden, die nicht versehentlich überschrieben werden können.
Symbol()
akzeptiert eine Beschreibung (oder einen „Symbolnamen“) als optionales Argument.
Diese Beschreibungen sind für den Debug-Prozess lesbare Labels und haben keinen Einfluss auf die Eindeutigkeit des Ergebnisses. Jeder Aufruf von Symbol
gibt ein völlig eindeutiges Symbolprimitiv zurück, auch wenn mehrere Aufrufe dieselbe Beschreibung haben:
Symbol( "My symbol." ) === Symbol( "My symbol." );
> false
Wie bei anderen primitiven Datentypen werden Symbole Methoden und Eigenschaften von ihrem Prototyp vererbt. Sie können beispielsweise auf eine Beschreibung als abgeleitete Eigenschaft des erstellten Symbols zugreifen:
let mySymbol = Symbol( "My symbol." );
mySymbol.description
> "My symbol."
Mit dem Schlüsselwort new
können Sie jedoch kein Symbol erstellen:
let mySymbol = new Symbol();
> Uncaught TypeError: Symbol is not a constructor
Symbole sind nicht aufzählbar. Das bedeutet, dass symbolische Eigenschaften nicht verfügbar sind, wenn Sie mit Standardmethoden über sie iterieren. Die Methode getOwnPropertySymbols()
bietet Zugriff auf die Symboleigenschaften eines Objekts.
Gemeinsam genutzte Symbole
Die Symbol.for()
-Methode versucht, alle vorhandenen Symbole in einer laufzeitweiten globalen Symbolregistrierung mit einem bestimmten String als Schlüssel abzurufen und gibt das übereinstimmende Symbol zurück, falls eines gefunden wird. Wenn kein Symbol gefunden wird, wird ein Symbol mit dem angegebenen Schlüssel erstellt und dem globalen Registry hinzugefügt:
let sharedSymbol = Symbol.for( "My key." );
sharedSymbol === Symbol.for( "My key." )
> true
Diese Schlüssel überschneiden sich funktional nicht mit den Beschreibungen, die von Nutzern erstellten Symbol
-Primitiven zugewiesen sind. Wenn Sie auf ein Symbol in der Symbolregistrierung zugreifen möchten, müssen Sie es zuerst mit for()
erstellen:
Symbol( "String" ) === Symbol( "String" );
> false
Symbol( "String" ) === Symbol.for( "String" );
> false
Symbol.for( "String" ) === Symbol.for( "String" );
> true
Verwenden Sie Symbol.keyFor()
, um den Schlüssel für ein beliebiges Symbol aus der Symbolregistrierung abzurufen:
let mySymbol = Symbol.for( "Key." );
Symbol.keyFor( mySymbol ) ;
> "Key."
„Gängige“ Symbole
Gängige Symbole sind statische Eigenschaften des Symbol
-Objekts, die jeweils selbst Symbole sind. Bekannte Symbole bieten eindeutige Attributschlüssel, um auf die integrierten Methoden von JavaScript zuzugreifen und sie zu ändern, und verhindern gleichzeitig, dass das Kernverhalten versehentlich überschrieben wird.
Symbol;
> function Symbol()
asyncIterator: Symbol(Symbol.asyncIterator)
for: function for()
hasInstance: Symbol("Symbol.hasInstance")
isConcatSpreadable: Symbol("Symbol.isConcatSpreadable")
iterator: Symbol(Symbol.iterator)
keyFor: function keyFor()
length: 0
match: Symbol("Symbol.match")
matchAll: Symbol("Symbol.matchAll")
name: "Symbol"
prototype: Object { … }
replace: Symbol("Symbol.replace")
search: Symbol("Symbol.search")
species: Symbol("Symbol.species")
split: Symbol("Symbol.split")
toPrimitive: Symbol("Symbol.toPrimitive")
toStringTag: Symbol("Symbol.toStringTag")
unscopables: Symbol("Symbol.unscopables")
<prototype>: function ()
Da Symbole eine ES6-spezifische Funktion sind, sollen diese symbolischen Werte als „Erweiterungspunkte“ für Entwickler verwendet werden, die das Verhalten von JavaScript ändern möchten, ohne Probleme mit der Abwärtskompatibilität zu verursachen.
Bekannte Symbolwerte werden oft mit einem Präfix von @@
oder in %
dargestellt, um ihre Schlüssel von ihren veränderbaren Prototypen zu unterscheiden. Beispiel: @@match
(oder %match%
) ist ein Verweis auf das unveränderliche Symbol.match
, nicht auf String.prototype.match
.
Wissen testen
Können Sie mit new
ein Symbol erstellen?
Welche der folgenden Optionen beschreiben „bekannte“ Symbole?