Detaillierte Erläuterung des primitiven Datentyps Symbol in JavaScript

Detaillierte Erläuterung des primitiven Datentyps Symbol in JavaScript

Einführung

Der einfachste Weg zum Erstellen einer Symbolvariable ist die Verwendung der Funktion Symbol(). Es gibt zwei Besonderheiten der Symbolvariablen:

1. Es kann als Objektattributname verwendet werden. Als Objektattributnamen können nur Zeichenfolgen- und Symboltypen verwendet werden.

2. Keine zwei Symbole haben den gleichen Wert.

const symbol1 = Symbol();
const symbol2 = Symbol();

symbol1 === symbol2; // falsch

const obj = {};
obj[symbol1] = 'Hallo';
obj[symbol2] = 'Welt';

obj[symbol1]; // 'Hallo'
obj[symbol2]; // 'Welt'

Obwohl es durch den Aufruf von Symbol() wie ein Objekt aussieht, handelt es sich bei Symbol tatsächlich um einen primitiven JavaScript-Datentyp. Die Verwendung von „new“ mit Symbol als Konstruktor führt zu einem Fehler.

const symbol1 = Symbol();

Typ von Symbol1; // 'Symbol'
symbol1 Instanz von Objekt; // falsch

// Wirft „TypeError: Symbol ist kein Konstruktor“
neues Symbol();

Beschreibung

Die Funktion Symbol() akzeptiert nur einen Parameter, die Zeichenfolgenbeschreibung. Dieser Zeichenfolgenparameter wird ausschließlich zur Unterstützung des Debuggens verwendet (sein toString()-Wert). Beachten Sie jedoch, dass zwei Symbole mit derselben Beschreibung nicht gleich sind.

const symbol1 = Symbol('mein Symbol');
const symbol2 = Symbol('mein Symbol');

symbol1 === symbol2; // falsch
console.log(symbol1); // 'Symbol(mein Symbol)'

Es gibt ein globales Symbolregister, und mit Symbol.for() erstellte Symbole werden diesem Register hinzugefügt und anhand ihrer Beschreibung indiziert. Das heißt, wenn Sie mit Symbol.for() zwei Symbole mit derselben Beschreibung erstellen, sind sie gleich.

const symbol1 = Symbol.for('test');
const symbol2 = Symbol.for('test');

symbol1 === symbol2; // wahr
console.log(symbol1); // 'Symbol(Test)'

Generell sollten Sie ohne triftigen Grund kein globales Register verwenden, da dies zu Namenskonflikten führen kann.

Namenskonflikte

JavaScript hat ein integriertes Symbol, nämlich Symbol.iterator in ES6. Objekte, die über eine Symbol.iterator-Funktion verfügen, werden als iterierbare Objekte bezeichnet, was bedeutet, dass Sie for/of-Schleifen auf dem Objekt anwenden können.

const fibonacci = {
  [Symbol.Iterator]: Funktion*() {
    sei a = 1;
    sei b = 1;
    lass temp;

    Ausbeute b;

    während (wahr) {
      temp = ein;
      a = a + b;
      b = Temperatur;
      Ausbeute b;
    }
  }
};

// Druckt jede Fibonacci-Zahl kleiner als 100
für (const x von Fibonacci) {
  wenn (x >= 100) {
    brechen;
  }
  console.log(x);
}

Warum hier Symbol.iterator statt String verwenden? Vorausgesetzt, dass Symbol.iterator nicht verwendet wird, muss das iterierbare Objekt ein String-Attribut mit dem Namen „Iterator“ haben, wie die folgende iterierbare Objektklasse:

Klasse MeineKlasse {
  Konstruktor(Objekt) {
    Objekt.zuweisen(dieses, obj);
  }

  Iterator() {
    const keys = Objekt.keys(dies);
    sei i = 0;
    return (Funktion*() {
      if (i >= Schlüssellänge) {
        zurückkehren;
      }
      ertrage Schlüssel[i++];
    })();
  }
}

Instanzen von MyClass sind iterierbare Objekte und Sie können die Eigenschaften des Objekts durchlaufen. Die obige Klasse hat jedoch einen potenziellen Fehler. Angenommen, ein böswilliger Benutzer übergibt ein Objekt mit einer Iteratoreigenschaft an den MyClass-Konstruktor:

const obj = new MyClass({ iterator: 'keine Funktion' });

Wenn Sie auf diese Weise for/of auf obj verwenden, wirft JavaScript eine TypeError-Ausnahme aus: obj ist nicht iterierbar. Es ist ersichtlich, dass die an das Objekt übergebene Iteratorfunktion die Iteratoreigenschaft der Klasse überschreibt. Dies ähnelt in gewisser Weise dem Sicherheitsproblem der Prototypenverschmutzung. Das gedankenlose Kopieren von Benutzerdaten verursacht Probleme bei einigen speziellen Eigenschaften wie __proto__ und Konstruktor.

Der entscheidende Punkt hierbei ist, dass das Symbol die internen Daten des Objekts und die Benutzerdaten getrennt hält. Da Symbole nicht in JSON dargestellt werden können, müssen Sie sich keine Sorgen machen, dass Sie Daten mit einer unangemessenen Symbol.iterator-Eigenschaft an die Express-API übergeben. Darüber hinaus können Sie bei Objekten, die integrierte Funktionen und Benutzerdaten mischen (z. B. Mongoose-Modelle), Symbole verwenden, um sicherzustellen, dass Benutzerdaten nicht mit integrierten Attributen in Konflikt geraten.

Private Immobilien

Da zwei beliebige Symbole nicht gleich sind, können sie problemlos zum Simulieren privater Eigenschaften in JavaScript verwendet werden. Symbole erscheinen nicht im Ergebnis von Object.keys(). Wenn Sie also nicht explizit ein Symbol exportieren oder es mithilfe von Object.getOwnPropertySymbols() abrufen, kann anderer Code nicht auf diese Eigenschaft zugreifen.

Funktion getObj() {
  const symbol = Symbol('test');
  const obj = {};
  obj[Symbol] = "Test";
  gibt Objekt zurück;
}

const obj = getObj();

Objekt.Schlüssel(obj); // []

// Sofern Sie keinen Verweis auf dieses Symbol haben, können Sie nicht auf diese Eigenschaft zugreifen obj[Symbol('test')]; // undefiniert

//Verwenden Sie getOwnPropertySymbols(), um dennoch eine Referenz auf das Symbol zu erhalten const [symbol] = Object.getOwnPropertySymbols(obj);
obj[symbol]; // 'Test'

Ein weiterer Grund ist, dass das Symbol nicht im Ergebnis von JSON.stringify() erscheint. Genauer gesagt ignoriert JSON.stringify() den Symbolattributnamen und den Attributwert:

const symbol = Symbol('test');
const obj = { [Symbol]: 'Test', Test: Symbol };

JSON.stringify(obj); // "{}"

Zusammenfassen

Die Verwendung von Symbolen zur Darstellung des internen Zustands eines Objekts kann Benutzerdaten und Programmzustand effektiv isolieren. Damit sind gewisse Namenskonventionen, wie beispielsweise das Beginnen interner Eigenschaften mit „$“, nicht mehr nötig. Versuchen Sie es das nächste Mal mit dem Symboltyp, wenn Sie eine private Eigenschaft definieren müssen!

Oben finden Sie eine ausführliche Erläuterung des primitiven JavaScript-Datentyps Symbol. Weitere Informationen zum primitiven JavaScript-Datentyp Symbol finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung der primitiven Datentypen Null und Undefined in JavaScript
  • Detaillierte Erklärung zweier neuer primitiver Datentypen in JavaScript (Record und Tuple)

<<:  Tutorial zur Installation und Konfiguration der Dekomprimierungsversion von mysql8.0.0 winx64.zip

>>:  So überprüfen Sie, ob die Ports des lokalen Computers und des Remote-Servers unter Linux verbunden sind

Artikel empfehlen

Vue implementiert die Drag & Drop-Sortierfunktion der Seiten-Div-Box

vue implementiert die Drag & Drop-Sortierfunk...

So konfigurieren Sie Java-Umgebungsvariablen im Linux-System

Konfigurieren von Java-Umgebungsvariablen Hier we...

Web-Standardanwendung: Neugestaltung der Tencent QQ-Homepage

Die Homepage von Tencent QQ wurde neu gestaltet un...

Der gesamte Prozess der Installation von Gogs mit Pagoda Panel und Docker

Inhaltsverzeichnis 1 Installieren Sie Docker im B...

Serielle und parallele Operationen in JavaScript

Inhaltsverzeichnis 1. Einleitung 2. es5-Methode 3...

So kaufen Sie einen Server und richten ihn zunächst ein

Ich habe eine Weile nicht mit Servern gearbeitet....

Details zu den Überwachungseigenschaften der Uhr in Vue

Inhaltsverzeichnis 1.watch überwacht Änderungen i...

So fügen Sie eindeutige Indizes für Felder in MySQL hinzu und löschen sie

1. PRIMARY KEY hinzufügen (Primärschlüsselindex) ...

Reines CSS3 zur Erzielung einer Mouseover-Schaltflächenanimation, Teil 2

Haben Sie nach den letzten beiden Kapiteln ein ne...