Dieser Beitrag handelt von Symbol()
, mit tatsächlichen Beispielen, die ich finden/erstellen konnte, und Fakten & Definitionen, die ich finden konnte.
TLDR;
Das Symbol()
ist der Datentyp, der mit der Veröffentlichung von ECMAScript 6 (ES6) eingeführt wurde.
Es gibt zwei interessante Fakten über das Symbol.
-
der erste Datentyp und einzige Datentyp in JavaScript, der kein Literal hat
-
irgendwelche Variablen, die mit Symbol()
definiert sind, erhalten einen eindeutigen Inhalt, aber es ist nicht wirklich privat.
-
irgendeine Daten haben ihr eigenes Symbol, und für die gleichen Daten wären die Symbole gleich. Weitere Informationen im nächsten Absatz, sonst ist es kein TLDR; :)
Wie initialisiere ich das Symbol?
1. Um eine eindeutige Kennung mit einem debugbaren Wert zu erhalten
Sie können es auf diese Weise tun:
var mySymbol1 = Symbol();
Oder auf diese Weise:
var mySymbol2 = Symbol("etwas Text hier");
Der String "etwas Text hier"
kann nicht aus dem Symbol extrahiert werden, es ist nur eine Beschreibung für Debugging-Zwecke. Es ändert das Verhalten des Symbols jedoch nicht. Allerdings könnten Sie es console.log
(was fair ist, da der Wert zum Debuggen ist, um diesen Log nicht mit einem anderen Logeintrag zu verwechseln):
console.log(mySymbol2);
// Symbol(etwas Text hier)
2. Um ein Symbol für einige Zeichendaten zu erhalten
In diesem Fall wird der Wert des Symbols tatsächlich berücksichtigt, und auf diese Weise können zwei Symbole nicht eindeutig sein.
var a1 = Symbol.for("test");
var a2 = Symbol.for("test");
console.log(a1 == a2); //true!
Nennen wir diese Symbole "Symbole des zweiten Typs". Sie haben keinen Zusammenhang mit den "Symbole des ersten Typs" (d.h. die mit Symbol(data)
definierten) in irgendeiner Weise.
Die nächsten beiden Absätze betreffen nur das Symbol des ersten Typs.
Wie profitiere ich von der Verwendung von Symbol anstelle der älteren Datentypen?
Lassen Sie uns zunächst ein Objekt betrachten, einen Standard-Datentyp. Wir könnten dort einige Schlüssel-Wert-Paare definieren und auf die Werte zugreifen, indem wir den Schlüssel angeben.
var personen = {"peter":"pan","jon":"doe"};
console.log(personen.peter);
// pan
Was ist, wenn wir zwei Personen mit dem Namen Peter haben?
Wenn wir dies tun:
var personen = {"peter":"first", "peter":"pan"};
würde nicht viel Sinn ergeben.
Es scheint also ein Problem zu sein, wenn zwei völlig unterschiedliche Personen denselben Namen haben. Lassen Sie uns dann auf unser neues Symbol()
verweisen. Es ist wie eine Person im wirklichen Leben - jede Person ist einzigartig, aber ihre Namen können gleich sein. Lassen Sie uns zwei "Personen" definieren.
var a = Symbol("peter");
var b = Symbol("peter");
Jetzt haben wir zwei verschiedene Personen mit demselben Namen. Sind unsere Personen wirklich unterschiedlich? Sie sind; Sie können dies überprüfen:
console.log(a == b);
// false
Wie profitieren wir davon?
Wir können zwei Einträge in Ihrem Objekt für die verschiedenen Personen machen, und sie können in keiner Weise verwechselt werden.
var erstePerson = Symbol("peter");
var zweitePerson = Symbol("peter");
var personen = {[erstePerson]:"first", [zweitePerson]:"pan"};
Hinweis:
Es ist jedoch erwähnenswert, dass das Umwandeln des Objekts mit JSON.stringify
alle mit einem Symbol initialisierten Paare mit einem Schlüssel Symbol()->Wert
entfernen wird.
Die Ausführung von Object.keys
wird ebenfalls keine solchen Symbol()->Wert
Paare zurückgeben.
Bei dieser Initialisierung ist es absolut unmöglich, die Einträge für die erste und zweite Person zu verwechseln. Wenn Sie console.log
für sie aufrufen, werden ihre Nachnamen korrekt ausgegeben.
console.log(personen[a]);
// first
console.log(personen[b]);
// pan
Wenn es in einem Objekt verwendet wird, wie unterscheidet es sich im Vergleich zur Definition einer nicht-aufzählbaren Eigenschaft?
In der Tat gab es bereits eine Möglichkeit, eine Eigenschaft zu definieren, die vor Object.keys
und Enumeration verborgen ist. Hier ist es:
var einObjekt = {};
var obst = "apfel";
Object.defineProperty( einObjekt, obst, {
enumerable: false,
value: "grün"
});
Was bringt das Symbol()
dort mit? Der Unterschied besteht darin, dass Sie die mit Object.defineProperty
definierte Eigenschaft immer auf übliche Weise erhalten können:
console.log(einObjekt[obst]); //grün
console.log(einObjekt["apfel"]); //grün
console.log(einObjekt.apfel); //grün
Und wenn wie im vorherigen Absatz mit Symbol definiert:
obst = Symbol("apfel");
Sie können den Wert nur erhalten, wenn Sie seine Variable kennen, d.h.
console.log(einObjekt[obst]); //grün
console.log(einObjekt["apfel"]); //undefined
console.log(einObjekt.apfel); //undefined
Darüber hinaus wird das Definieren einer weiteren Eigenschaft unter dem Schlüssel "apfel"
dazu führen, dass das Objekt die ältere verliert (und wenn fest codiert, könnte es einen Fehler werfen). Also, keine Äpfel mehr! Das ist schade. Bezugnehmend auf den vorherigen Absatz sind die Symbole einzigartig, und das Definieren eines Schlüssels als Symbol()
macht ihn einzigartig.
Typumwandlung und -überprüfung
-
Im Gegensatz zu anderen Datentypen ist es unmöglich, das Symbol()
in einen anderen Datentyp umzuwandeln.
-
Es ist möglich, ein Symbol auf der Grundlage eines primitiven Datentyps durch Aufrufen von Symbol(data)
zu "erstellen".
-
In Bezug auf die Überprüfung des Typs ändert sich nichts.
function isSymbol ( variable ) {
return typeof someSymbol === "symbol";
}
var ein_Symbol = Symbol("hallo!");
var überhaupt_Nicht_Ein_Symbol = "hallo";
console.log(isSymbol(ein_Symbol)); //true
console.log(isSymbol(überhaupt_Nicht_Ein_Symbol)); //false