Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

Experiment: Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.

Öffentliche Klassenfelder

BaselineWidely available

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

Syntax

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

Es gibt einige zusätzliche Syntaxeinschränkungen:

  • Der Name einer statischen Eigenschaft (Feld oder Methode) kann nichtprototype sein.
  • Der Name eines Klassenfeldes (statisch oder instanziert) kann nichtconstructor sein.

Beschreibung

Diese Seite führt öffentliche Instanzfelder im Detail ein.

Öffentliche Instanzfelder existieren in jeder erstellten Instanz einer Klasse. Durch das Deklarieren eines öffentlichen Feldes können 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 Konstruktorkörper Ablauf nimmt) hinzugefügt oder direkt nachdemsuper() in einer Unterklasse zurückkehrt. Felder ohne Initialisierer werden zuundefined initialisiert. Wie Eigenschaften können 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")); // trueconsole.log(instance.field); // undefinedconsole.log(instance.fieldWithInitializer); // "instance field"console.log(instance.prefixField); // "prefixed field"

Berechnete Feldnamen werden nur einmal zurKlassendefinitionszeit ausgewertet. Das bedeutet, dass jede Klasse immer eine feste Menge von Feldnamen hat und zwei Instanzen nicht unterschiedliche Feldnamen über berechnete Namen haben können. Derthis-Wert im berechneten Ausdruck ist das umgebendethis der Klassendefinition, und das Verweisen auf den Klassennamen führt zu einemReferenceError, da die Klasse noch nicht initialisiert ist.await undyield 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 sichthis auf die sich im Aufbau befindende Klasseninstanz, undsuper bezieht sich auf dieprototype-Eigenschaft der Basisklasse, die die Instanzmethoden der Basisklasse enthält, 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 derthis-Wert für 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 könnenawait oderyield im Initialisiererausdruck nicht verwenden. (Betrachten Sie den Initialisiererausdruck als implizit in eine Funktion eingebettet.)

Da Instanzfelder einer Klasse hinzugefügt werden, bevor der jeweilige Konstruktor abläuft, können Sie die Werte der Felder innerhalb des Konstruktors abrufen. Da jedoch Instanzfelder einer abgeleiteten Klasse nach der Rückkehr vonsuper() 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: 1console.log(instance.field); // 2

Felder werden einzeln hinzugefügt. Feldinitialisierer können sich auf Feldwerte oberhalb davon beziehen, jedoch nicht auf solche darunter. Alle Instanz- und statischen Methoden werden vorab hinzugefügt und können aufgerufen werden, obwohl deren Verhalten möglicherweise 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); // 3console.log(instance.b); // undefined

Hinweis:Dies ist besonders wichtig beiprivaten Feldern, da das Zugreifen auf ein nicht initialisiertes privates Feld einenTypeError auslöst, selbst wenn das private Feld darunter deklariert ist. (Wenn das private Feld nicht deklariert ist, wäre es ein früherSyntaxError.)

Da Klassenfelder mithilfe der[[DefineOwnProperty]]-Semantik hinzugefügt werden (was im WesentlichenObject.defineProperty() entspricht), lösen Feldeklarationen in abgeleiteten Klassen keine Setter in der Basisklasse aus. Dieses Verhalten unterscheidet sich von der Verwendung vonthis.field = … im Konstruktor.

js
class Base {  set field(val) {    console.log(val);  }}class DerivedWithField extends Base {  field = 1;}const instance = new DerivedWithField(); // No logclass 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, einschließlichBabel undtsc, Klassenfelder in dieDerivedWithConstructor-Form, was nach der Standardisierung von Klassenfeldern zu subtilen Fehlern führte.

Beispiele

Verwendung von Klassenfeldern

Klassenfelder können nicht von Argumenten des Konstruktors abhängen, daher evaluieren Feldinitialisierer normalerweise für 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 ermöglicht, 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 demthis dynamisch mutiert wird: Die explizite Felderklärung macht klar, welche Felder definitiv in der Instanz vorhanden sein werden.

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

Da Initialisierer ausgeführt werden, nachdem die Basisklasse ausgeführt wurde, können 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

Specification
ECMAScript® 2026 Language Specification
# prod-FieldDefinition

Browser-Kompatibilität

Siehe auch

MDN-Feedback-Box

Diese Seite wurde automatisch aus dem Englischen übersetzt.


[8]ページ先頭

©2009-2025 Movatter.jp