Wie erstelle ich ein “öffentliches statisches Feld” in einer ES6-Klasse?

Lesezeit: 7 Minuten

Wie erstelle ich ein offentliches statisches Feld in einer ES6 Klasse
aebabis

Ich erstelle eine Javascript-Klasse und möchte ein öffentliches statisches Feld wie in Java haben. Dies ist der entsprechende Code:

export default class Agent {
    CIRCLE: 1,
    SQUARE: 2,
    ...

Dies ist der Fehler, den ich bekomme:

line 2, col 11, Class properties must be methods. Expected '(' but instead saw ':'.

Es sieht so aus, als ob ES6-Module dies nicht zulassen. Gibt es eine Möglichkeit das gewünschte Verhalten zu erreichen oder muss ich einen Getter schreiben?

Wie erstelle ich ein offentliches statisches Feld in einer ES6 Klasse
Kangax

Sie erstellen ein “öffentliches statisches Feld” mit einem Accessor und einem “statischen” Schlüsselwort:

class Agent {
    static get CIRCLE() {
      return 1;
    }
    static get SQUARE() {
      return 2;
    }
}

Agent.CIRCLE; // 1

Betrachten Sie eine Spezifikation, 14,5 — Klassendefinitionen — Sie würden etwas verdächtig Relevantes sehen 🙂

KlasseElement[Yield] :
Methodendefinition[?Yield]

statisch Methodendefinition[?Yield] ;

Von dort kannst du also folgen 14.5.14 — Laufzeitsemantik: ClassDefinitionEvaluation — um zu überprüfen, ob es wirklich tut, was es tut. Schritt 20:

  1. Für jedes ClassElement m in der Reihenfolge von Methoden
    1. Wenn IsStatic von m ist falsch, dann
      1. Status sei das Ergebnis der PropertyDefinitionEvaluation für m mit den Argumenten proto und false.
    2. Anders,
      1. Status sei das Ergebnis der PropertyDefinitionEvaluation für m mit den Argumenten F und false.
    3. Wenn der Status ein abrupter Abschluss ist, dann
      1. Setzen Sie die LexicalEnvironment des ausgeführten Ausführungskontexts auf lex.
      2. Rückgabestatus.

IsStatic wurde früher in . definiert 14.5.9

ClassElement : static MethodDefinition
Rückgabe wahr.

So PropertyMethodDefinition wird mit “F” (Konstruktor, Funktionsobjekt) als Argument aufgerufen, was wiederum erstellt eine Accessor-Methode für dieses Objekt.

Dies funktioniert schon zumindest in IETP (Tech-Preview), sowie 6to5- und Traceur-Compilern.

  • Für alle anderen, die suchen, werden die statischen Accessoreigenschaften in Node. :-/ kangax.github.io/compat-table/es6/…

    – David Hernandez

    6. Juni ’15 um 19:05


  • Ab Node.js 6.x+ wird dies unterstützt.

    – NuSkooler

    18. Februar ’17 um 19:46

  • Beachten Sie, dass Sie bei Verwendung von Flow eine Zeile hinzufügen müssen unsafe.enable_getters_and_setters=true zu deiner .flowconfig unter [options] (was nervt).

    – Kristina

    1. März ’18 um 15:29

  • Dies wird bei mir nicht funktionieren Ich erhalte “` Nicht behandelte Ablehnung TypeError: Cannot set property dataHashKey of class Collections { api_1 | statisch get dataHashKey() { api_1 | ‘Sammlungen’ zurückgeben; api_1 | } “`

    – Pavan

    14. November ’18 um 10:11


  • Kangax, vielleicht liege ich da falsch, aber ich denke, Sie sind der Entwickler von Stoffen, oder zumindest kennen Sie sich sehr gut mit Stoffen aus. Ich habe zwei offene Fragen, die ich lösen muss, um mit meinem Projekt fortzufahren. Könntest du so nett sein und sie dir anschauen?

    – SIMBIOSE surl

    23. August ’21 um 2:46

1641908382 753 Wie erstelle ich ein offentliches statisches Feld in einer ES6 Klasse
Timothy Gu

Seit ECMAScript 2022 können Sie ähnlich wie bei traditionellen klassenorientierten Sprachen wie Java und C# Folgendes tun:

class MyClass {
    static myStaticProp = 42;
    myProp = 42;
    myProp2 = this.myProp;
    myBoundFunc = () => { console.log(this.myProp); };

    constructor() {
        console.log(MyClass.myStaticProp); // Prints '42'
        console.log(this.myProp); // Prints '42'
        this.myBoundFunc(); // Prints '42'
    }
}

Das obige ist äquivalent zu:

class MyClass {
    constructor() {
        this.myProp = 42;
        this.myProp2 = this.myProp;
        this.myBoundFunc = () => { console.log(this.myProp); };

        console.log(MyClass.myStaticProp); // Prints '42'
        console.log(this.myProp); // Prints '42'
        this.myBoundFunc(); // Prints '42'
    }
}
MyClass.myStaticProp = 42;

Die Funktionen wurden in der hinzugefügt “Statische Klassenfunktionen” und “Klassenfelder” Vorschläge von Daniel Ehrenberg et al. Google Chrome (und das neue Edge) unterstützen beide Vorschläge in Version 72, gleichwertig Node.js 12+. Firefox unterstützt öffentliche Instanzfelder seit Version 69 und statische Instanzfelder seit Version 75. Safari unterstützt beides seit Version 14.1. Weitere Informationen finden Sie unter caniuse.com.

Für ältere Browser, die diese Funktionen noch nicht unterstützen, können Sie Babel zu transpilieren Klasse Felder. Dies erfordert @babel/plugin-proposal-class-properties aktiviert werden (standardmäßig aktiviert in @babel/plugin-env ab v7.14.0).


Im Vergleich zur Lösung von @kangax, einen Getter zu deklarieren, kann diese Lösung auch performanter sein, da hier direkt auf die Eigenschaft zugegriffen wird, anstatt eine Funktion aufzurufen.


Bearbeiten: Ein Vorschlag für einheitliche Klassenfelder befindet sich jetzt in Stufe 3.

Bearbeiten (Februar 2020): Die statischen Klassenfeatures wurden in einen anderen Vorschlag aufgeteilt. Danke @GOTO0!

Bearbeiten (März 2021): Mit Ausnahme von Safari unterstützen jetzt alle gängigen Browser, die nach April 2020 veröffentlicht wurden, diese Funktion!

Bearbeiten (Juni 2021): Beide Vorschläge werden angenommen von TC39, das ECMAScript-Sprachkomitee, und Safari haben diese Funktion in Version 14.1 bereitgestellt!

  • Ich denke, der relevante Vorschlag ist eigentlich Dieses hier (Statische Klassenfunktionen).

    – GOTO 0

    4. Juli ’19 um 21:16

1641908382 679 Wie erstelle ich ein offentliches statisches Feld in einer ES6 Klasse
Dai

In aktuellen Entwürfen von ECMAScript 6 (Stand Februar 2015) müssen alle Klasseneigenschaften Methoden sein, keine Werte (Beachten Sie, dass in ECMAScript eine “Eigenschaft” im Konzept einem OOP-Feld ähnelt, außer dass der Feldwert a . sein muss Function Objekt, kein anderer Wert wie a Number oder Object).

Sie können diese weiterhin mit traditionellen ECMAScript-Konstruktor-Eigenschaftsspezifizierern angeben:

 class Agent {
 }
 Agent.CIRCLE = 1;
 Agent.SQUARE = 2;
 ...

  • Beachten Sie, dass der ES6 class Syntax ist ohnehin nur syntaktischer Zucker für traditionelle JS-Konstruktorfunktionen und -Prototypen.

    – Matt Browne

    11. Februar ’15 um 2:54

  • Ich denke, Sie möchten diese Eigenschaften auf den Prototyp und nicht auf den Konstruktor legen, damit sie über Eigenschaftsreferenzen von Instanzen sichtbar sind.

    – Spitz

    11. Februar ’15 um 3:02

  • @Pointy Ich habe gefolgert, dass das OP versucht, Konstanten als Referenz zu speichern (fast wie ein C # / .NET .). enum).

    – Dai

    11. Februar ’15 um 3:04

  • @MattBrowne Ja, aber um es klar zu sagen class Syntax weist auch gewisse nuancierte Unterschiede auf. Zum Beispiel eine Methode, die mit deklariert wurde Class.prototype.method = function () {}; ist aufzählbar (sichtbar mit for-in-Schleifen), während class Methoden sind nicht aufzählbar.

    – Timothy Gu

    13. Mai ’17 um 22:35

Wie erstelle ich ein offentliches statisches Feld in einer ES6 Klasse
SM Adnan

Um die Vorteile der statischen Variablen voll auszuschöpfen, folgte ich diesem Ansatz. Um genauer zu sein, können wir es verwenden, um eine private Variable zu verwenden oder nur einen öffentlichen Getter zu haben oder sowohl Getter als auch Setter zu haben. Im letzten Fall ist es dasselbe wie eine der oben geposteten Lösungen.

var Url = (() => {
    let _staticMember = [];
    return class {
        static getQueries(hash = document.location.hash) {
            return hash;
        }

        static get staticMember(){
            return _staticMember;
        }
    };
})();

Usages:
console.log(Url.staticMember); // [];
Url.staticMember.push('it works');
console.log(Url.staticMember); // ['it works'];

Ich konnte eine weitere Klasse erstellen, die die URL erweitert, und es funktionierte.

Ich habe babel verwendet, um meinen ES6-Code in ES5 umzuwandeln

1641908382 713 Wie erstelle ich ein offentliches statisches Feld in einer ES6 Klasse
Legende80er

Die Antwort von @kangax imitiert nicht das gesamte statische Verhalten traditioneller OOP-Sprachen, da Sie nicht auf die statische Eigenschaft über ihre Instanz zugreifen können const agent = new Agent; agent.CIRCLE; // Undefined

Wenn Sie auf statische Eigenschaften wie OOPs zugreifen möchten, ist hier meine Lösung:

class NewApp {
  get MULTIPLE_VERSIONS_SUPPORTED() {
    return this.constructor.MULTIPLE_VERSIONS_SUPPORTED; // Late binding for inheritance
  }
}

NewApp.MULTIPLE_VERSIONS_SUPPORTED = true;

Testen Sie den Code wie folgt.

class NewApp {
  get MULTIPLE_VERSIONS_SUPPORTED() {
    console.log('this.constructor.name:', this.constructor.name); // late binding
    return this.constructor.MULTIPLE_VERSIONS_SUPPORTED;
  }
}

// Static property can be accessed by class
NewApp.MULTIPLE_VERSIONS_SUPPORTED = true;

const newApp = new NewApp;

// Static property can be accessed by it's instances
console.log('newApp.MULTIPLE_VERSIONS_SUPPORTED:', newApp.MULTIPLE_VERSIONS_SUPPORTED); // true

// Inheritance
class StandardApp extends NewApp {}

// Static property can be inherited
console.log('StandardApp.MULTIPLE_VERSIONS_SUPPORTED:', StandardApp.MULTIPLE_VERSIONS_SUPPORTED); // true

// Static property can be overwritten
StandardApp.MULTIPLE_VERSIONS_SUPPORTED = false;

const std = new StandardApp;

console.log('std.MULTIPLE_VERSIONS_SUPPORTED:', std.MULTIPLE_VERSIONS_SUPPORTED); // false

  • Zugriff auf a static Feld durch eine Instanz wäre eher ungewöhnlich, würden Sie nicht sagen? In einigen Sprachen, wie beispielsweise Java, geben IDEs tatsächlich eine Warnung/einen Hinweis aus, wenn Sie so etwas tun.

    – Isac

    13. Mai ’18 um 22:31


  • @Isac Ja du hast recht. Vom Zugriff per Instanz wird abgeraten, ebenso wie meine Antwort. Nur eine andere Perspektive der Lösung. 😀.

    – Legende80er

    14. Dez. 18 um 3:50

  • Zugriff auf a static Feld durch eine Instanz wäre eher ungewöhnlich, würden Sie nicht sagen? In einigen Sprachen, wie beispielsweise Java, geben IDEs tatsächlich eine Warnung/einen Hinweis aus, wenn Sie so etwas tun.

    – Isac

    13. Mai ’18 um 22:31


  • @Isac Ja du hast recht. Vom Zugriff per Instanz wird abgeraten, ebenso wie meine Antwort. Nur eine andere Perspektive der Lösung. 😀.

    – Legende80er

    14. Dez. 18 um 3:50

.

360430cookie-checkWie erstelle ich ein “öffentliches statisches Feld” in einer ES6-Klasse?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy