Heim  >  Artikel  >  Web-Frontend  >  Zusammenfassung der Implementierung privater Variablen in ES6 (Codebeispiel)

Zusammenfassung der Implementierung privater Variablen in ES6 (Codebeispiel)

不言
不言nach vorne
2018-11-21 11:25:491646Durchsuche

Dieser Artikel bietet Ihnen eine Zusammenfassung der Implementierung privater Variablen in ES6 (Codebeispiele). Ich hoffe, dass er für Freunde hilfreich ist.

Als ich „Einführung in ECMAScript 6“ las, sah ich verstreute Implementierungen privater Variablen, daher werde ich es hier zusammenfassen.

1. Vereinbarung

Umsetzung

class Example {
    constructor() {
        this._private = 'private';
    }
    getName() {
        return this._private
    }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // private

Vorteile

  1. Einfache Schreibmethode

  2. Einfaches Debuggen

  3. Gute Kompatibilität

Nachteile

  1. Externer Zugriff und Änderung

  2. Die Sprache verfügt über keinen Koordinationsmechanismus. Beispielsweise listet die for in-Anweisung alle Attribute auf

  3. Namenskonflikt

2. Schließung

implementiert einen

/**
 * 实现一
 */
class Example {
  constructor() {
    var _private = '';
    _private = 'private';
    this.getName = function() {return _private}
  }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // undefined

Vorteile

  1. Kein Namenskonflikt

  2. Extern nicht möglich Zugriff und Änderung

Nachteile

  1. Die Logik des Konstruktors wird kompliziert. Der Konstruktor sollte nun nur die Objektinitialisierung durchführen, um private Variablen zu implementieren, und die Implementierung einiger Methoden ist etwas unklar.

  2. Methoden existieren auf Instanzen, nicht auf Prototypen, und Unterklassen können super nicht zum Aufrufen verwenden

  3. Die Konstruktion verursacht etwas Mehraufwand

Implementierung 2

/**
 * 实现二
 */
const Example = (function() {
  var _private = '';

  class Example {
    constructor() {
      _private = 'private';
    }
    getName() {
      return _private;
    }
  }

  return Example;

})();

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // undefined

Vorteile

  1. Kein Namenskonflikt

  2. Externe können nicht darauf zugreifen und Änderungen vornehmen

Nachteile

  1. Die Schreibmethode ist etwas kompliziert

  2. Die Konstruktion verursacht etwas Mehraufwand

3. Symbol

Implementierung

const Example = (function() {
    var _private = Symbol('private');

    class Example {
        constructor() {
          this[_private] = 'private';
        }
        getName() {
          return this[_private];
        }
    }

    return Example;
})();

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined

Vorteile

  1. Kein Namenskonflikt

  2. Kann von außen nicht aufgerufen und geändert werden

  3. Kein Leistungsverlust

Nachteile

  1. Leicht geschrieben Komplex

  2. Kompatibilität ist auch gut

4. WeakMap

Implementierung

/**
 * 实现一
 */
const _private = new WeakMap();

class Example {
  constructor() {
    _private.set(this, 'private');
  }
  getName() {
      return _private.get(this);
  }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined

wenn So geschrieben, haben Sie möglicherweise das Gefühl, dass die Kapselung nicht ausreicht. Sie können auch so schreiben:

/**
 * 实现二
 */
const Example = (function() {
  var _private = new WeakMap(); // 私有成员存储容器

  class Example {
    constructor() {
      _private.set(this, 'private');
    }
    getName() {
        return _private.get(this);
    }
  }

  return Example;
})();

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined

Vorteile

  1. Keine Namenskonflikte

  2. Extern Zugriff und Änderung nicht möglich

Nachteile

  1. Die Schreibmethode ist mühsam

  2. Es gibt einige Kompatibilitätsprobleme

  3. Es gibt einen gewissen Leistungsaufwand

5. Der neueste Vorschlag

class Point {
  #x;
  #y;

  constructor(x, y) {
    this.#x = x;
    this.#y = y;
  }

  equals(point) {
    return this.#x === point.#x && this.#y === point.#y;
  }
}

Warum also nicht direkt private Felder nutzen? Zum Beispiel:

class Foo {
  private value;

  equals(foo) {
    return this.value === foo.value;
  }
}

Um es einfach auszudrücken, es ist zu mühsam, und natürlich gibt es Leistungsaspekte ...

Zum Beispiel, wenn wir nicht # verwenden, sondern privat Schlüsselwort :

class Foo {
  private value = '1';

  equals(foo) {
    return this.value === foo.value;
  }
}

var foo1 = new Foo();
var foo2 = new Foo();

console.log(foo1.equals(foo2));

Hier erstellen wir zwei neue Instanzen und übergeben dann foo2 als Parameter an die Instanzmethode von foo1.

Können wir also den Wert von foo2.value ermitteln? Wenn wir direkt foo2.value werden, können wir den Wert definitiv nicht erhalten. Schließlich handelt es sich um eine private Variable, aber equal ist eine Klassenmethode von Foo. Können wir ihn also erhalten?

Die Antwort ist ja.

Tatsächlich ist dies auch in anderen Sprachen wie Java und C++ der Fall. Mitgliedsfunktionen einer Klasse können auf private Variablen von Instanzen desselben Typs zugreifen Für die Implementierung werden „externe“ Informationen innerhalb der Klasse selbst ausgeblendet. Es ist nicht erforderlich, den Zugriff auf private Variablen zu verbieten. Darüber hinaus kann dies auch der Fall sein Bieten Sie Benutzern Komfort.

Da es möglich ist, den Wert abzurufen, sollte das gedruckte Ergebnis wahr sein, aber was ist, wenn der Wert, den wir übergeben, keine Instanz von Foo, sondern ein anderes Objekt ist?

var foo1 = new Foo();

console.log(foo1.equals({
  value: 2
}));

Natürlich kann der Code hier normal ausgeführt werden, aber für den Compiler ist es etwas problematisch, da der Compiler nicht weiß, ob der Wert ein normales Attribut oder ein privates Attribut von foo ist, also muss der Compiler dies tun Um ein Urteil zu fällen, bestimmen Sie zunächst, ob foo eine Instanz von Foo ist, und ermitteln Sie dann den Wert.

Dies bedeutet auch, dass eine solche Beurteilung für jeden Attributzugriff getroffen werden muss. Die Engine wurde rund um den Attributzugriff stark optimiert und ist zu träge zum Ändern, was auch die Geschwindigkeit verringert.

Aber zusätzlich zu dieser Arbeit gibt es noch einige andere Dinge zu beachten, wie zum Beispiel:

  1. Sie müssen den privaten Schlüssel in jede lexikalische Umgebung kodieren

  2. Können diese Eigenschaften durchquert werden?

  3. Wenn private Attribute und normale Attribute denselben Namen haben, wer blockiert dann wen?

  4. So verhindern Sie, dass die Namen privater Attribute erkannt werden.

Weitere Informationen zur Verwendung von # anstelle von privat finden Sie in dieser Ausgabe.

Natürlich können diese Probleme gelöst werden, aber sie sind etwas lästig.

Und wenn Sie # wählen, hat die Implementierungsmethode nichts mit den JavaScript-Objekteigenschaften zu tun. Sie verwendet die Methode private slots und eine neue Slot-Suchsyntax. Kurz gesagt, sie ist einfacher als die private Implementierungsmethode.

Das obige ist der detaillierte Inhalt vonZusammenfassung der Implementierung privater Variablen in ES6 (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen