Wie erstelle ich ein “öffentliches statisches Feld” in einer ES6-Klasse?
Lesezeit: 7 Minuten
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?
Welche ECMAScript 6-Engine-Implementierung verwenden Sie?
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
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.
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
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:
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
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
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
.
3604300cookie-checkWie erstelle ich ein “öffentliches statisches Feld” in einer ES6-Klasse?yes
Welche ECMAScript 6-Engine-Implementierung verwenden Sie?
– Dai
11. Februar ’15 um 2:54
@Dai github.com/ModuleLoader/es6-module-loader
– aebabis
11. Februar ’15 um 3:07