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

So installieren Sie die PHP7 Redis-Erweiterung auf CentOS7

Einführung Im vorherigen Artikel haben wir Redis ...

Der Unterschied zwischen redundanten und doppelten Indizes in MySQL

MySQL ermöglicht das Erstellen mehrerer Indizes f...

Detailliertes Beispiel des MySQL InnoDB-Sperrmechanismus

1. InnoDB-Sperrmechanismus Die InnoDB-Speicher-En...

HTML-Elemente (Tags) und ihre Verwendung

a : Gibt die Start- oder Zielposition eines Hyper...

Eine detaillierte Einführung in die Verwendung von Blockkommentaren in HTML

Allgemeine Kommentare in HTML: <!--XXXXXXXX--&g...

Verwenden von JS zum Implementieren eines einfachen Rechners

Verwenden Sie JS, um einen einfachen Rechner für ...

Mobile Web-Bildschirmanpassung (rem)

Vorwort Ich habe vor Kurzem meine bisherigen Noti...

Beispielcode zur Implementierung einer Hohlmaskenebene mit CSS

Inhalt dieses Artikels: Seitenhohlmaskenebene, Se...

Designideen für MySQL-Backup und -Wiederherstellung

Hintergrund Lassen Sie mich zunächst den Hintergr...

So zeigen Sie alle laufenden Prozesse in Linux an

Sie können den Befehl ps verwenden. Es kann relev...

Detaillierte Erklärung langer Transaktionsbeispiele in MySQL

Vorwort: Die Artikelserie „Erste Schritte mit MyS...

MySQL-Operator-Zusammenfassung

Inhaltsverzeichnis 1. Arithmetische Operatoren 2....