[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Classes/Private_elements [Back]  [Original]

Private Elemente - JavaScript | MDN

Dieser Inhalt wurde automatisch aus dem Englischen bersetzt, und kann Fehler enthalten. Erfahre mehr ber dieses Experiment.

View in English Always switch to English

Private Elemente

Baseline Weitgehend verfgbar

Diese Funktion ist gut etabliert und funktioniert auf vielen Gerten und in vielen Browserversionen. Sie ist seit Juli 2021 browserbergreifend verfgbar.

Private Elemente sind Gegenstcke zu regulren Klassen-Elementen, die ffentlich sind, einschlielich Klassenfelder, Klassenmethoden usw. Private Elemente werden durch einen Hash-Prfix # erstellt und knnen auerhalb der Klasse nicht legal referenziert werden. Die Datenschutzeinkapselung dieser Klassenelemente wird von JavaScript selbst durchgesetzt. Der einzige Weg, um auf ein privates Element zuzugreifen, ist ber die Punkt-Notation, und dies ist nur innerhalb der Klasse mglich, die das private Element definiert.

Private Elemente waren vor dem Vorhandensein dieser Syntax nicht nativ in der Sprache. In der prototypischen Vererbung kann ihr Verhalten mit WeakMap-Objekten oder Closures nachgeahmt werden, aber sie knnen im Hinblick auf Ergonomie nicht mit der #-Syntax verglichen werden.

Hinweis: Auf MDN vermeiden wir den Begriff "private Eigenschaft". Eine Eigenschaft in JavaScript hat einen Zeichenfolgen- oder Symbol-Schlssel und Attribute wie writable, enumerable und configurable, aber private Elemente haben keine dieser Attribute. Obwohl private Elemente mit der vertrauten Punkt-Notation zugegriffen werden, knnen sie nicht proxy-fhig gemacht, aufgezhlt, gelscht oder mit einer Object Methode interagiert werden.

In diesem Artikel

Syntax

js
class ClassWithPrivate {
  #privateField;
  #privateFieldWithInitializer = 42;

  #privateMethod() {
    // 
  }

  static #privateStaticField;
  static #privateStaticFieldWithInitializer = 42;

  static #privateStaticMethod() {
    // 
  }
}

Es gibt einige zustzliche Syntaxbeschrnkungen:

  • Alle innerhalb einer Klasse deklarierten privaten Bezeichner mssen einzigartig sein. Der Namensraum wird zwischen statischen und Instanz-Elementen geteilt. Die einzige Ausnahme ist, wenn die beiden Deklarationen ein Getter-Setter-Paar definieren.
  • Der private Bezeichner kann nicht #constructor sein.

Beschreibung

Die meisten Klassenelemente haben ihre privaten Gegenstcke:

  • Private Felder
  • Private Methoden
  • Private statische Felder
  • Private statische Methoden
  • Private Getter
  • Private Setter
  • Private statische Getter
  • Private statische Setter

Diese Funktionen werden zusammenfassend als private Elemente bezeichnet. Allerdings knnen Konstruktoren in JavaScript nicht privat sein. Um zu verhindern, dass Klassen auerhalb der Klasse instanziiert werden, mssen Sie eine private Flagge verwenden.

Private Elemente werden mit # Namen (ausgesprochen Hash-Namen) deklariert, d.h. Bezeichner, die mit # beginnen. Das Hash-Prfix ist ein wesentlicher Bestandteil des Eigenschaftennamens man kann es mit der alten Unterstrich-Prfix-Konvention _privateField in Verbindung bringen aber es ist keine gewhnliche Zeichenfolgen-Eigenschaft, daher kann man nicht dynamisch mit der Klammer-Notation darauf zugreifen.

Es ist ein Syntaxfehler, auf #-Namen auerhalb der Klasse zu verweisen. Es ist auch ein Syntaxfehler, auf private Elemente zu verweisen, die nicht im Klassenrumpf deklariert wurden, oder zu versuchen, deklarierte Elemente mit delete zu entfernen.

js
class ClassWithPrivateField {
  #privateField;

  constructor() {
    delete this.#privateField; // Syntax error
    this.#undeclaredField = 42; // Syntax error
  }
}

const instance = new ClassWithPrivateField();
instance.#privateField; // Syntax error

JavaScript, als dynamische Sprache, ist in der Lage, diese berprfung zur Kompilierzeit durchzufhren, dank der speziellen Hash-Bezeichner-Syntax, die sie auf der Syntaxebene von normalen Eigenschaften unterscheidet.

Hinweis: Code, der in der Chrome-Konsole ausgefhrt wird, kann auf private Elemente auerhalb der Klasse zugreifen. Dies ist eine nur in DevTools geltende Entspannung der JavaScript-Syntaxbeschrnkung.

Wenn Sie auf ein privates Element von einem Objekt zugreifen, das das Element nicht hat, wird ein TypeError ausgelst, anstatt wie bei normalen Eigenschaften undefined zurckzugeben.

js
class C {
  #x;

  static getX(obj) {
    return obj.#x;
  }
}

console.log(C.getX(new C())); // undefined
console.log(C.getX({})); // TypeError: Cannot read private member #x from an object whose class did not declare it

Dieses Beispiel zeigt auch, dass Sie auf private Elemente innerhalb von statischen Funktionen und auch auf extern definierte Instanzen der Klasse zugreifen knnen.

Sie knnen den in Operator verwenden, um zu berprfen, ob ein extern definiertes Objekt ein privates Element besitzt. Dies gibt true zurck, wenn das private Feld oder die private Methode existiert, und false andernfalls.

js
class C {
  #x;
  constructor(x) {
    this.#x = x;
  }
  static getX(obj) {
    if (#x in obj) return obj.#x;

    return "obj must be an instance of C";
  }
}
console.log(C.getX(new C("foo"))); // "foo"
console.log(C.getX(new C(0.196))); // 0.196
console.log(C.getX(new C(new Date()))); // the current date and time
console.log(C.getX({})); // "obj must be an instance of C"

Beachten Sie einen Korollar aus privaten Namen, die immer vor-deklariert und nicht lschbar sind: Wenn Sie festgestellt haben, dass ein Objekt ein privates Element der aktuellen Klasse besitzt (entweder aus einem try...catch oder einer in-Prfung), muss es alle anderen privaten Elemente besitzen. Dass ein Objekt die privaten Elemente einer Klasse besitzt, bedeutet in der Regel, dass es von dieser Klasse konstruiert wurde (obwohl nicht immer).

Private Elemente sind kein Teil des prototypischen Vererbung-Modells, da sie nur innerhalb des Krper der aktuellen Klasse zugnglich sind und nicht von Unterklassen geerbt werden. Private Elemente mit demselben Namen in verschiedenen Klassen sind vllig unterschiedlich und arbeiten nicht miteinander. Betrachten Sie sie als externe Metadaten, die an jede Instanz angehngt und von der Klasse verwaltet werden. Aus diesem Grund klont structuredClone() keine privaten Elemente und Object.freeze() sowie Object.seal() haben keine Auswirkungen auf private Elemente.

Fr weitere Informationen darber, wie und wann private Felder initialisiert werden, siehe ffentliche Klassenfelder.

Beispiele

Private Felder

Private Felder umfassen private Instanzfelder und private statische Felder. Private Felder sind nur innerhalb der Klassendeklaration zugnglich.

Private Instanzfelder

Wie ihre ffentlichen Gegenstcke, private Instanzfelder:

  • werden hinzugefgt, bevor der Konstruktor in einer Basisklasse ausgefhrt wird oder unmittelbar nachdem super() in einer Unterklasse aufgerufen wurde, und
  • sind nur auf Instanzen der Klasse verfgbar.
js
class ClassWithPrivateField {
  #privateField;

  constructor() {
    this.#privateField = 42;
  }
}

class Subclass extends ClassWithPrivateField {
  #subPrivateField;

  constructor() {
    super();
    this.#subPrivateField = 23;
  }
}

new Subclass(); // In some dev tools, it shows Subclass {#privateField: 42, #subPrivateField: 23}

Hinweis: #privateField aus der ClassWithPrivateField Basisklasse ist privat fr ClassWithPrivateField und von der abgeleiteten Subclass nicht zugnglich.

Zurckgeben eines berschreibenden Objekts

Ein Konstruktor einer Klasse kann ein anderes Objekt zurckgeben, das als neues this fr den Konstruktor der abgeleiteten Klasse verwendet wird. Die abgeleitete Klasse kann dann private Felder auf diesem zurckgegebenen Objekt definieren was bedeutet, dass es mglich ist, private Felder auf nicht verwandte Objekte zu "stempeln".

js
class Stamper extends class {
  // A base class whose constructor returns the object it's given
  constructor(obj) {
    return obj;
  }
} {
  // This declaration will "stamp" the private field onto the object
  // returned by the base class constructor
  #stamp = 42;
  static getStamp(obj) {
    return obj.#stamp;
  }
}

const obj = {};
new Stamper(obj);
// `Stamper` calls `Base`, which returns `obj`, so `obj` is
// now the `this` value. `Stamper` then defines `#stamp` on `obj`

console.log(obj); // In some dev tools, it shows {#stamp: 42}
console.log(Stamper.getStamp(obj)); // 42
console.log(obj instanceof Stamper); // false

// You cannot stamp private elements twice
new Stamper(obj); // Error: Initializing an object twice is an error with private fields

Warnung: Dies ist potenziell sehr verwirrend. Es wird im Allgemeinen empfohlen, nichts vom Konstruktor zurckzugeben insbesondere nichts, das nicht mit this zu tun hat.

Private statische Felder

Wie ihre ffentlichen Gegenstcke, private statische Felder:

  • werden zur Klassenkonstruktorzeit zur Klasse hinzugefgt, und
  • sind nur auf der Klasse selbst verfgbar.
js
class ClassWithPrivateStaticField {
  static #privateStaticField = 42;

  static publicStaticMethod() {
    return ClassWithPrivateStaticField.#privateStaticField;
  }
}

console.log(ClassWithPrivateStaticField.publicStaticMethod()); // 42

Es gibt eine Einschrnkung fr private statische Felder: Nur die Klasse, die das private statische Feld definiert, kann auf das Feld zugreifen. Dies kann zu unerwartetem Verhalten fhren, wenn this verwendet wird. Im folgenden Beispiel bezieht sich this auf die Subclass Klasse (nicht auf die ClassWithPrivateStaticField Klasse), wenn wir versuchen, Subclass.publicStaticMethod() aufzurufen, und verursacht daher einen TypeError.

js
class ClassWithPrivateStaticField {
  static #privateStaticField = 42;

  static publicStaticMethod() {
    return this.#privateStaticField;
  }
}

class Subclass extends ClassWithPrivateStaticField {}

Subclass.publicStaticMethod(); // TypeError: Cannot read private member #privateStaticField from an object whose class did not declare it

Dies ist das gleiche, wenn Sie die Methode mit super aufrufen, da super-Methoden nicht mit der Superklasse als this aufgerufen werden.

js
class ClassWithPrivateStaticField {
  static #privateStaticField = 42;

  static publicStaticMethod() {
    // When invoked through super, `this` still refers to Subclass
    return this.#privateStaticField;
  }
}

class Subclass extends ClassWithPrivateStaticField {
  static callSuperMethod() {
    return super.publicStaticMethod();
  }
}

Subclass.callSuperMethod(); // TypeError: Cannot read private member #privateStaticField from an object whose class did not declare it

Es wird empfohlen, auf private statische Felder immer ber den Klassennamen zuzugreifen und nicht ber this, damit die Vererbung die Methode nicht unterbricht.

Private Methoden

Private Methoden umfassen private Instanzmethoden und private statische Methoden. Private Methoden sind nur innerhalb der Klassendeklaration zugnglich.

Private Instanzmethoden

Im Gegensatz zu ihren ffentlichen Gegenstcken, private Instanzmethoden:

  • werden unmittelbar bevor die Instanzfelder installiert, installiert, und
  • sind nur auf Instanzen der Klasse und nicht auf ihrer .prototype-Eigenschaft verfgbar.
js
class ClassWithPrivateMethod {
  #privateMethod() {
    return 42;
  }

  publicMethod() {
    return this.#privateMethod();
  }
}

const instance = new ClassWithPrivateMethod();
console.log(instance.publicMethod()); // 42

Private Instanzmethoden knnen Generator-, asynchrone oder asynchrone Generatorfunktionen sein. Private Getter und Setter sind ebenfalls mglich und folgen den gleichen Syntaxanforderungen wie ihre ffentlichen Getter und Setter Gegenstcke.

js
class ClassWithPrivateAccessor {
  #message;

  get #decoratedMessage() {
    return `${this.#message}`;
  }
  set #decoratedMessage(msg) {
    this.#message = msg;
  }

  constructor() {
    this.#decoratedMessage = "hello world";
    console.log(this.#decoratedMessage);
  }
}

new ClassWithPrivateAccessor(); // hello world

Im Gegensatz zu ffentlichen Methoden sind private Methoden nicht auf der .prototype-Eigenschaft ihrer Klasse zugnglich.

js
class C {
  #method() {}

  static getMethod(x) {
    return x.#method;
  }
}

console.log(C.getMethod(new C())); // [Function: #method]
console.log(C.getMethod(C.prototype)); // TypeError: Receiver must be an instance of class C

Private statische Methoden

Wie ihre ffentlichen Gegenstcke, private statische Methoden:

  • werden zur Klassenkonstruktorzeit zur Klasse hinzugefgt, und
  • sind nur auf der Klasse selbst verfgbar.
js
class ClassWithPrivateStaticMethod {
  static #privateStaticMethod() {
    return 42;
  }

  static publicStaticMethod() {
    return ClassWithPrivateStaticMethod.#privateStaticMethod();
  }
}

console.log(ClassWithPrivateStaticMethod.publicStaticMethod()); // 42

Private statische Methoden knnen Generator-, asynchrone oder asynchrone Generatorfunktionen sein.

Die zuvor erwhnte Einschrnkung fr private statische Felder gilt auch fr private statische Methoden und kann ebenfalls zu unerwartetem Verhalten fhren, wenn this verwendet wird. Im folgenden Beispiel bezieht sich this auf die Subclass Klasse (nicht auf die ClassWithPrivateStaticMethod Klasse), wenn wir versuchen, Subclass.publicStaticMethod() aufzurufen, und verursacht daher einen TypeError.

js
class ClassWithPrivateStaticMethod {
  static #privateStaticMethod() {
    return 42;
  }

  static publicStaticMethod() {
    return this.#privateStaticMethod();
  }
}

class Subclass extends ClassWithPrivateStaticMethod {}

console.log(Subclass.publicStaticMethod()); // TypeError: Cannot read private member #privateStaticMethod from an object whose class did not declare it

Simulieren privater Konstruktoren

Viele andere Sprachen bieten die Mglichkeit, einen Konstruktor als privat zu kennzeichnen, was verhindert, dass die Klasse auerhalb der Klasse selbst instanziiert wird Sie knnen nur statische Fabrikmethoden verwenden, die Instanzen erstellen, oder gar keine Instanzen erstellen. JavaScript hat keine native Mglichkeit, dies zu tun, aber es kann durch die Verwendung einer privaten statischen Flag implementiert werden.

js
class PrivateConstructor {
  static #isInternalConstructing = false;

  constructor() {
    if (!PrivateConstructor.#isInternalConstructing) {
      throw new TypeError("PrivateConstructor is not constructable");
    }
    PrivateConstructor.#isInternalConstructing = false;
    // More initialization logic
  }

  static create() {
    PrivateConstructor.#isInternalConstructing = true;
    const instance = new PrivateConstructor();
    return instance;
  }
}

new PrivateConstructor(); // TypeError: PrivateConstructor is not constructable
PrivateConstructor.create(); // PrivateConstructor {}

Spezifikationen

Spezifikation
ECMAScript 2027 LanguageSpecification
# prod-PrivateIdentifier

Browser-Kompatibilitt

javascript.classes.private_class_fields

javascript.classes.private_class_fields_in

javascript.classes.private_class_methods

Siehe auch


Web Proxy Viewer  |  New URL  |  Original Page