it-swarm.com.de

Was ist die Motivation, um Symbole auf ES6 zu bringen?

[~ # ~] Update [~ # ~] : Vor kurzem ist ein genialer Artikel von Mozilla aufgetaucht. Lies es, wenn du neugierig bist.

Wie Sie vielleicht wissen, handelt es sich dabei um die Aufnahme ist geplant einen neuen primitiven Symboltyp in ECMAScript 6 (ganz zu schweigen von anderen verrückten Dingen). Ich dachte immer, dass die :symbol Idee in Ruby ist unnötig; wir könnten stattdessen einfach einfache Zeichenfolgen verwenden, wie wir es in JavaScript tun. Und jetzt beschließen sie, die Dinge in JS damit zu komplizieren.

Ich verstehe die Motivation nicht. Könnte mir jemand erklären, ob wir wirklich Symbole in JavaScript brauchen?

336
Yanis

Die ursprüngliche Motivation für die Einführung von Symbolen in Javascript bestand darin, private Eigenschaften zu aktivieren.

Leider wurden sie stark herabgestuft. Sie sind nicht mehr privat, da Sie sie über Reflektion finden können, z. B. mit Object.getOwnPropertySymbols oder Proxies.

Sie werden jetzt als eindeutige Symbole bezeichnet und dienen nur dazu, Namenskonflikte zwischen Eigenschaften zu vermeiden. Beispielsweise kann ECMAScript selbst jetzt Erweiterungs-Hooks über bestimmte Methoden einführen, die Sie Objekten zuweisen können (z. B. um deren Iterationsprotokoll zu definieren), ohne zu riskieren, dass sie mit Benutzernamen kollidieren.

Ob das stark genug ist, um der Sprache Symbole hinzuzufügen, ist umstritten.

211

Symbole garantieren keine echte Privatsphäre, können jedoch verwendet werden, um öffentliche und interne Eigenschaften von Objekten zu trennen. Nehmen wir ein Beispiel, in dem wir Symbol für private Eigenschaften verwenden können.

Nehmen wir ein Beispiel, in dem eine Eigenschaft eines Objekts nicht privat ist.

var Pet = (function() {
  function Pet(type) {
    this.type = type;
  }
  Pet.prototype.getType = function() {
    return this.type;
  }
  return Pet;
}());

var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Modified outside
console.log(a.getType());//Output: null

Oben ist die Klasseneigenschaft Pettype nicht privat. Um es privat zu machen, müssen wir einen Abschluss erstellen. Das folgende Beispiel zeigt, wie wir type mit einem Closure privat machen können.

var Pet = (function() {
  function Pet(type) {
    this.getType = function(){
      return type;
    };
  }
  return Pet;
}());

var b = new Pet('dog');
console.log(b.getType());//dog
b.type = null;
//Stays private
console.log(b.getType());//dog

Nachteil des obigen Ansatzes: Wir führen einen zusätzlichen Abschluss für jede Pet - Instanz ein, der die Leistung beeinträchtigen kann.

Nun führen wir Symbol ein. Dies kann uns helfen, eine Immobilie privat zu machen, ohne zusätzliche unnötige Schließungen zu verwenden. Codebeispiel unten:

var Pet = (function() {
  var typeSymbol = Symbol('type');
  function Pet(type) {
    this[typeSymbol] = type;
  }
  Pet.prototype.getType = function(){
    return this[typeSymbol];
  }
  return Pet;
}());

var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Stays private
console.log(a.getType());//Output: dog
89
Samar Panda

Symbols sind neue, spezielle Objekte, die als eindeutiger Eigenschaftsname in Objekten verwendet werden können. Durch die Verwendung von Symbol anstelle von string können verschiedene Module Eigenschaften erstellen, die nicht miteinander in Konflikt stehen. Symbols kann auch privat gemacht werden, sodass niemand auf ihre Eigenschaften zugreifen kann, der noch keinen direkten Zugriff auf Symbol hat.

Symbols ist ein neues Grundelement . Genau wie die Grundelemente number, string und boolean verfügt Symbol über eine Funktion, mit der sie erstellt werden können. Im Gegensatz zu den anderen Primitiven hat Symbols keine wörtliche Syntax (z. B. wie string'') - Sie können sie nur mit dem Konstruktor Symbol auf folgende Weise erstellen:

let symbol = Symbol();

In Wirklichkeit sind Symbol 's nur eine etwas andere Möglichkeit, Eigenschaften an ein Objekt anzuhängen - Sie könnten die bekannten Symbols einfach als Standardmethoden bereitstellen, genau wie Object.prototype.hasOwnProperty, das in allem vorkommt, was von Object erbt.

Hier sind einige der Vorteile des primitiven Typs Symbol.

Symbols haben Debug-Fähigkeit eingebaut

Symbols kann mit einer Beschreibung versehen werden, die eigentlich nur zum Debuggen verwendet wird, um die Protokollierung in einer Konsole zu vereinfachen.

Symbols kann als Object Schlüssel verwendet werden

Hier wird Symbol wirklich interessant. Sie sind stark mit Gegenständen verflochten. Symbol kann Objekten als Schlüssel zugewiesen werden. Dies bedeutet, dass Sie einem Objekt eine unbegrenzte Anzahl von eindeutigen Symbol - Schlüsseln zuweisen können und garantiert ist, dass diese niemals mit string - Schlüsseln in Konflikt stehen andere eindeutige Symbols.

Symbols kann als eindeutiger Wert verwendet werden.

Nehmen wir an, Sie haben eine Protokollierungsbibliothek, die mehrere Protokollebenen enthält, z. B. logger.levels.DEBUG, logger.levels.INFO, logger.levels.WARN und so weiter. In ES5-Code möchten Sie diese strings (also logger.levels.DEBUG === 'debug') oder numbers (logger.levels.DEBUG === 10). Beide sind nicht ideal, da diese Werte keine eindeutigen Werte sind, aber Symbols sind! Damit logger.levels wird einfach:

log.levels = {
  DEBUG: Symbol('debug'),
  INFO: Symbol('info'),
  WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');

Lesen Sie mehr in diesem toller Artikel.

35

In diesem Beitrag geht es um die Symbol(), die aktuelle Beispiele enthält, die ich finden/machen konnte, sowie Fakten und Definitionen, die ich finden konnte.

TLDR;

Die Funktion Symbol() ist der Datentyp, der mit dem Release von ECMAScript 6 (ES6) eingeführt wurde.

Es gibt zwei merkwürdige Tatsachen über das Symbol.

  • der erste und einzige Datentyp in JavaScript, der kein Literal enthält

  • jede mit Symbol() definierte Variable erhält eindeutigen Inhalt, aber nicht wirklich privat .

  • alle Daten haben ein eigenes Symbol, und für dieselben Daten wären die Symbole dasselbe. Weitere Informationen finden Sie im folgenden Abschnitt. Andernfalls handelt es sich nicht um eine TLRD. :)

Wie initialisiere ich das Symbol?

1. Um eine eindeutige Kennung mit einem debuggbaren Wert zu erhalten

Du kannst es entweder so machen:

var mySymbol1 = Symbol();

Oder so:

var mySymbol2 = Symbol("some text here");

Die Zeichenfolge "some text here" Kann nicht aus dem Symbol extrahiert werden, sondern ist nur eine Beschreibung für Debugging-Zwecke. Es ändert nichts am Verhalten des Symbols. Sie können es jedoch console.log (Was fair ist, da der Wert für das Debuggen ist, um dieses Protokoll nicht mit einem anderen Protokolleintrag zu verwechseln):

console.log(mySymbol2);
// Symbol(some text here)

2. Um ein Symbol für einige Zeichenfolgendaten 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 überschneiden sich in keiner Weise mit den Symbolen des "ersten Typs" (d. H. Den mit Symbol(data) definierten Symbolen).

Die nächsten beiden Absätze betreffen nur das Symbol first-type.

Wie kann ich von der Verwendung von Symbol anstelle der älteren Datentypen profitieren?

Betrachten wir zunächst ein Objekt, einen Standarddatentyp. Wir könnten dort einige Schlüssel-Wert-Paare definieren und durch Angabe des Schlüssels auf die Werte zugreifen.

var persons = {"peter":"pan","jon":"doe"};
console.log(persons.peter);
// pan

Was ist, wenn wir zwei Personen mit dem Namen Peter haben?

Dies tun:

var persons = {"peter":"first", "peter":"pan"};

würde nicht viel Sinn machen.

Es scheint also ein Problem von zwei absolut unterschiedlichen Personen zu sein, die denselben Namen haben. Verweisen wir dann auf das neue Symbol(). Es ist wie eine Person im wirklichen Leben - jede Person ist einzigartig, aber ihre Namen können gleich sein. Definieren wir zwei "Personen".

 var a = Symbol("peter");
 var b = Symbol("peter");

Jetzt haben wir zwei verschiedene Personen mit demselben Namen. Unterscheiden sich unsere Personen wirklich? Sie sind; Sie können dies überprüfen:

 console.log(a == b);
 // false

Wie profitieren wir dort?

Wir können in Ihrem Objekt zwei Einträge für die verschiedenen Personen vornehmen, und diese können in keiner Weise verwechselt werden.

 var firstPerson = Symbol("peter");
 var secondPerson = Symbol("peter");
 var persons = {[firstPerson]:"first", [secondPerson]:"pan"};

Hinweis:
Es ist jedoch zu beachten, dass bei der Zeichenfolge des Objekts mit JSON.stringify Alle mit einem Symbol als Schlüssel initialisierten Paare gelöscht werden.
Wenn Sie Object.keys Ausführen, werden auch diese Symbol()->value Paare nicht zurückgegeben.

Mit dieser Initialisierung ist es absolut unmöglich, die Eingaben für die erste und zweite Person zu verwechseln. Wenn Sie für sie console.log Aufrufen, wird der zweite Name korrekt ausgegeben.

 console.log(persons[a]);
 // first
 console.log(persons[b]);
 // pan

Wie unterscheidet sich die Verwendung in object von der Definition einer nicht aufzählbaren Eigenschaft?

In der Tat gab es bereits eine Möglichkeit, eine Eigenschaft zu definieren, die vor Object.keys Und Aufzählung verborgen werden soll. Hier ist es:

var anObject = {};
var fruit = "Apple";    

Object.defineProperty( anObject, fruit, {
    enumerable: false,
    value: "green"
});

Welchen Unterschied bringt Symbol() dorthin? Der Unterschied besteht darin, dass Sie die mit Object.defineProperty Definierte Eigenschaft wie gewohnt erhalten können:

console.log(anObject[fruit]); //green
console.log(anObject["Apple"]); //green
console.log(anObject.Apple); //green

Und wenn mit Symbol wie im vorherigen Absatz definiert:

fruit = Symbol("Apple");

Sie können seinen Wert nur erhalten, wenn Sie seine Variable kennen, d. H.

console.log(anObject[fruit]); //green
console.log(anObject["Apple"]); //undefined
console.log(anObject.Apple); //undefined

Wenn Sie eine andere Eigenschaft unter dem Schlüssel "Apple" Definieren, wird das ältere Objekt gelöscht (und wenn es fest codiert ist, kann es einen Fehler auslösen). Also keine Äpfel mehr! Das ist schade. Unter Bezugnahme auf den vorherigen Absatz sind die Symbole eindeutig, und die Definition eines Schlüssels als Symbol() macht ihn eindeutig.

Typkonvertierung und Überprüfung

  • Im Gegensatz zu anderen Datentypen kann Symbol() nicht in einen anderen Datentyp konvertiert werden.

  • Es ist möglich, ein Symbol basierend auf dem primitiven Datentyp durch Aufrufen von Symbol(data) zu "machen".

  • Bei der Überprüfung des Typs ändert sich nichts.

    function isSymbol ( variable ) {
        return typeof someSymbol === "symbol";
    }
    
    var a_Symbol = Symbol("hey!");
    var totally_Not_A_Symbol = "hey";
    
    console.log(isSymbol(a_Symbol)); //true
    console.log(isSymbol(totally_Not_A_Symbol)); //false
    

34
nicael

So sehe ich es. Symbole bieten ein zusätzliches Maß an Datenschutz, indem sie verhindern, dass die Schlüssel/Eigenschaften eines Objekts durch einige gängige Methoden wie Object.keys () und JSON.stringify () verfügbar gemacht werden.

var age = Symbol();  // declared in another module perhaps?
class Person {
   constructor(n,a){
      this.name = n;
      this[age] = a;  
   }
   introduce(){
       console.log(`My name is ${this.name}. I am ${this[age]-10}.`);
   }
}
var j = new Person('Jane',45);
j.introduce();  // My name is Jane. I am 35.
console.log(JSON.stringify(j)); // {"name":"Jane"}
console.log(Object.keys(j)); // ["name"]
console.log(j[age]); // 45   (well…only if you know the age in the first place…)

Obwohl ein Objekt per se angegeben wird, können solche Eigenschaften weiterhin durch Reflektion, Proxy, Object.getOwnPropertySymbols () usw. verfügbar gemacht werden. Es gibt jedoch keine natürlichen Mittel, um über einige direkte Methoden auf sie zuzugreifen, die manchmal von einem OOP Perspektive.

17
Chong Lip Phang

Ein JS-Symbol ist ein neuer primitiver Datentyp. Dies sind Token, die als eindeutige IDs dienen. Ein Symbol kann mit dem Konstruktor Symbol erstellt werden. Nehmen Sie zum Beispiel diesen Ausschnitt aus MDN:

// The symbol constructor takes one optional argument, 
// the descriptions which is used for debugging only.
// Here are two symbols with the same description
let Sym1 = Symbol("Sym");
let Sym2 = Symbol("Sym");
  
console.log(Sym1 == Sym2); // returns "false"
// Symbols are guaranteed to be unique.
// Even if we create many symbols with the same description,
// they are different values.

Es ist oft praktisch, Symbole als eindeutige Objekteigenschaftsschlüssel zu verwenden, zum Beispiel:

let obj = {};
let prop = Symbol();

obj[prop] = 123;  // the symbol prop is assigned 123
obj.prop  = 456;  // the string prop is assigned 456

console.log(obj.prop, obj[prop]); // logs 456, 123
0