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

ffentliche Klassenfelder - 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

ffentliche Klassenfelder

Baseline Weitgehend verfgbar

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

ffentliche Felder sind beschreibbare, durchsuchbare und konfigurierbare Eigenschaften, die auf jeder Klasseninstanz oder Klassenkonstruktor definiert sind.

In diesem Artikel

Syntax

js
class ClassWithField {
  instanceField;
  instanceFieldWithInitializer = "instance field";
  static staticField;
  static staticFieldWithInitializer = "static field";
}

Es gibt einige zustzliche Syntaxeinschrnkungen:

  • Der Name einer statischen Eigenschaft (Feld oder Methode) kann nicht prototype sein.
  • Der Name eines Klassenfeldes (statisch oder instanziert) kann nicht constructor sein.

Beschreibung

Diese Seite fhrt ffentliche Instanzfelder im Detail ein.

ffentliche Instanzfelder existieren in jeder erstellten Instanz einer Klasse. Durch das Deklarieren eines ffentlichen Feldes knnen Sie sicherstellen, dass das Feld immer vorhanden ist, und die Klassendefinition wird selbstdokumentierender.

ffentliche Instanzfelder werden der Instanz entweder zur Konstruktionszeit in der Basisklasse (bevor der Konstruktorkrper Ablauf nimmt) hinzugefgt oder direkt nachdem super() in einer Unterklasse zurckkehrt. Felder ohne Initialisierer werden zu undefined initialisiert. Wie Eigenschaften knnen Feldnamen berechnet werden.

js
const PREFIX = "prefix";

class ClassWithField {
  field;
  fieldWithInitializer = "instance field";
  [`${PREFIX}Field`] = "prefixed field";
}

const instance = new ClassWithField();
console.log(Object.hasOwn(instance, "field")); // true
console.log(instance.field); // undefined
console.log(instance.fieldWithInitializer); // "instance field"
console.log(instance.prefixField); // "prefixed field"

Berechnete Feldnamen werden nur einmal zur Klassendefinitionszeit ausgewertet. Das bedeutet, dass jede Klasse immer eine feste Menge von Feldnamen hat und zwei Instanzen nicht unterschiedliche Feldnamen ber berechnete Namen haben knnen. Der this-Wert im berechneten Ausdruck ist das umgebende this der Klassendefinition, und das Verweisen auf den Klassennamen fhrt zu einem ReferenceError, da die Klasse noch nicht initialisiert ist. await und yield funktionieren in diesem Ausdruck wie erwartet.

js
class C {
  [Math.random()] = 1;
}

console.log(new C());
console.log(new C());
// Both instances have the same field name

Im Feldinitialisierer bezieht sich this auf die sich im Aufbau befindende Klasseninstanz, und super bezieht sich auf die prototype-Eigenschaft der Basisklasse, die die Instanzmethoden der Basisklasse enthlt, jedoch nicht deren Instanzfelder.

js
class Base {
  baseField = "base field";
  anotherBaseField = this.baseField;
  baseMethod() {
    return "base method output";
  }
}

class Derived extends Base {
  subField = super.baseMethod();
}

const base = new Base();
const sub = new Derived();

console.log(base.anotherBaseField); // "base field"

console.log(sub.subField); // "base method output"

Der Ausdruck des Feldinitialisierers wird jedes Mal ausgewertet, wenn eine neue Instanz erstellt wird. (Da der this-Wert fr jede Instanz unterschiedlich ist, kann der Initialisiererausdruck auf instanzspezifische Eigenschaften zugreifen.)

js
class C {
  obj = {};
}

const instance1 = new C();
const instance2 = new C();
console.log(instance1.obj === instance2.obj); // false

Der Ausdruck wird synchron ausgewertet. Sie knnen await oder yield im Initialisiererausdruck nicht verwenden. (Betrachten Sie den Initialisiererausdruck als implizit in eine Funktion eingebettet.)

Da Instanzfelder einer Klasse hinzugefgt werden, bevor der jeweilige Konstruktor abluft, knnen Sie die Werte der Felder innerhalb des Konstruktors abrufen. Da jedoch Instanzfelder einer abgeleiteten Klasse nach der Rckkehr von super() definiert werden, hat der Konstruktor der Basisklasse keinen Zugriff auf die Felder der abgeleiteten Klasse.

js
class Base {
  constructor() {
    console.log("Base constructor:", this.field);
  }
}

class Derived extends Base {
  field = 1;
  constructor() {
    super();
    console.log("Derived constructor:", this.field);
    this.field = 2;
  }
}

const instance = new Derived();
// Base constructor: undefined
// Derived constructor: 1
console.log(instance.field); // 2

Felder werden einzeln hinzugefgt. Feldinitialisierer knnen sich auf Feldwerte oberhalb davon beziehen, jedoch nicht auf solche darunter. Alle Instanz- und statischen Methoden werden vorab hinzugefgt und knnen aufgerufen werden, obwohl deren Verhalten mglicherweise nicht wie erwartet ist, wenn sie auf Felder unterhalb des initialisierten Feldes verweisen.

js
class C {
  a = 1;
  b = this.c;
  c = this.a + 1;
  d = this.c + 1;
}

const instance = new C();
console.log(instance.d); // 3
console.log(instance.b); // undefined

Hinweis: Dies ist besonders wichtig bei privaten Feldern, da das Zugreifen auf ein nicht initialisiertes privates Feld einen TypeError auslst, selbst wenn das private Feld darunter deklariert ist. (Wenn das private Feld nicht deklariert ist, wre es ein frher SyntaxError.)

Da Klassenfelder mithilfe der [[DefineOwnProperty]]-Semantik hinzugefgt werden (was im Wesentlichen Object.defineProperty() entspricht), lsen Feldeklarationen in abgeleiteten Klassen keine Setter in der Basisklasse aus. Dieses Verhalten unterscheidet sich von der Verwendung von this.field = im Konstruktor.

js
class Base {
  set field(val) {
    console.log(val);
  }
}

class DerivedWithField extends Base {
  field = 1;
}

const instance = new DerivedWithField(); // No log

class DerivedWithConstructor extends Base {
  constructor() {
    super();
    this.field = 1;
  }
}

const instance2 = new DerivedWithConstructor(); // Logs 1

Hinweis: Bevor die Klassenspezifikation mit der [[DefineOwnProperty]]-Semantik finalisiert wurde, transformierten die meisten Transpiler, einschlielich Babel und tsc, Klassenfelder in die DerivedWithConstructor-Form, was nach der Standardisierung von Klassenfeldern zu subtilen Fehlern fhrte.

Beispiele

Verwendung von Klassenfeldern

Klassenfelder knnen nicht von Argumenten des Konstruktors abhngen, daher evaluieren Feldinitialisierer normalerweise fr jede Instanz denselben Wert (es sei denn, derselbe Ausdruck kann jedes Mal zu unterschiedlichen Werten evaluiert werden, wie z.B. Math.random() oder Objektinitialisierer).

js
class Person {
  name = nameArg; // nameArg is out of scope of the constructor
  constructor(nameArg) {}
}
js
class Person {
  // All instances of Person will have the same name
  name = "Dragomir";
}

Dennoch ist selbst die Deklaration eines leeren Klassenfeldes vorteilhaft, da sie auf die Existenz des Feldes hinweist, was Typtests und menschlichen Lesern ermglicht, die Struktur der Klasse statisch zu analysieren.

js
class Person {
  name;
  age;
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

Der obige Code scheint wiederholend zu sein, aber betrachten Sie den Fall, in dem this dynamisch mutiert wird: Die explizite Felderklrung macht klar, welche Felder definitiv in der Instanz vorhanden sein werden.

js
class Person {
  name;
  age;
  constructor(properties) {
    Object.assign(this, properties);
  }
}

Da Initialisierer ausgefhrt werden, nachdem die Basisklasse ausgefhrt wurde, knnen Sie auf Eigenschaften zugreifen, die vom Konstruktor der Basisklasse erstellt wurden.

js
class Person {
  name;
  age;
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

class Professor extends Person {
  name = `Professor ${this.name}`;
}

console.log(new Professor("Radev", 54).name); // "Professor Radev"

Spezifikationen

Spezifikation
ECMAScript 2027 LanguageSpecification
# prod-FieldDefinition

Browser-Kompatibilitt

Siehe auch


Web Proxy Viewer  |  New URL  |  Original Page