Estoy haciendo una clase de Javascript y me gustaría tener un campo estático público como en Java. Este es el código relevante:
export default class Agent {
CIRCLE: 1,
SQUARE: 2,
...
Este es el error que obtengo:
line 2, col 11, Class properties must be methods. Expected '(' but instead saw ':'.
Parece que los módulos ES6 no permiten esto. ¿Hay alguna manera de obtener el comportamiento deseado o tengo que escribir un captador?
javascript
ecmascript-6
class-fields
Aebabis
fuente
fuente

Respuestas:
Usted crea un "campo estático público" usando un descriptor de acceso y una palabra clave "estática":
class Agent { static get CIRCLE() { return 1; } static get SQUARE() { return 2; } } Agent.CIRCLE; // 1Mirando una especificación, 14.5 - Definiciones de clase - verías algo sospechosamente relevante :)
Entonces, desde allí, puede seguir a 14.5.14 - Runtime Semantics: ClassDefinitionEvaluation - para verificar si realmente hace lo que parece. Específicamente, paso 20:
IsStatic se define anteriormente en 14.5.9
Así
PropertyMethodDefinitionse llama con "F" (constructor, objeto de función) como argumento, que a su vez crea un método de acceso en ese objeto .Esto ya funciona en al menos IETP (vista previa técnica), así como en los compiladores 6to5 y Traceur.
fuente
unsafe.enable_getters_and_setters=truea su .flowconfig debajo[options](lo cual es molesto).Existe una propuesta de ECMAScript de etapa 3 llamada "Características de clase estática" de Daniel Ehrenberg y Jeff Morrison que tiene como objetivo resolver este problema. Junto con la propuesta de "Campos de clase" de la etapa 3 , el código futuro se verá así:
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' } }Lo anterior es equivalente a:
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;Babel admite la transpiración de campos de clase a través de @ babel / plugin-proposition-class-properties (incluido en el ajuste preestablecido de la etapa 3 ), de modo que puede usar esta función incluso si su tiempo de ejecución de JavaScript no la admite.
En comparación con la solución de @ kangax de declarar un getter, esta solución también puede ser más eficaz, ya que aquí se accede a la propiedad directamente en lugar de llamar a una función.
Si se acepta esta propuesta, entonces será posible escribir código JavaScript de una manera más similar a los lenguajes tradicionales orientados a objetos como Java y C♯.
Editar : una propuesta de campos de clase unificada se encuentra ahora en la etapa 3; actualice a los paquetes de Babel v7.x.
Editar (febrero de 2020) : las características de la clase estática se han dividido en una propuesta diferente. ¡Gracias @ GOTO0!
fuente
En los borradores actuales de ECMAScript 6 (a febrero de 2015), todas las propiedades de clase deben ser métodos, no valores (tenga en cuenta que en ECMAScript una "propiedad" es similar en concepto a un campo OOP, excepto que el valor del campo debe ser un
Functionobjeto, no cualquier otro valor como aNumberoObject).Aún puede especificarlos utilizando los especificadores de propiedad del constructor ECMAScript tradicionales:
class Agent { } Agent.CIRCLE = 1; Agent.SQUARE = 2; ...fuente
classsintaxis de ES6 es simplemente azúcar sintáctica para las funciones y prototipos de constructores JS tradicionales de todos modos.enum).classsintaxis también tiene ciertas diferencias matizadas. Por ejemplo, un método declarado conClass.prototype.method = function () {};es enumerable (visible con bucles for-in), mientras que losclassmétodos no son enumerables.Para aprovechar al máximo la variable estática, seguí este enfoque. Para ser más específicos, podemos usarlo para usar una variable privada o tener solo un getter público, o tener ambos getter o setter. En el último caso, es igual a una de las soluciones publicadas anteriormente.
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'];Podría crear otra clase ampliando la URL y funcionó.
Usé babel para convertir mi código ES6 a ES5
fuente
class Url { static getQueries… }; Url.staticMember = [];habría sido mucho más sencillo?===comparaciones tanto el rendimientofalse, por ciertoLa respuesta de @kangax no imita todo el comportamiento estático de los lenguajes OOP tradicionales, porque no puede acceder a la propiedad estática por su instancia como
const agent = new Agent; agent.CIRCLE; // UndefinedSi desea acceder a una propiedad estática como OOP, aquí está mi solución:
class NewApp { get MULTIPLE_VERSIONS_SUPPORTED() { return this.constructor.MULTIPLE_VERSIONS_SUPPORTED; // Late binding for inheritance } } NewApp.MULTIPLE_VERSIONS_SUPPORTED = true;Pruebe el código de la siguiente manera.
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); // falsefuente
staticcampo mediante una instancia sería bastante poco común, ¿no crees? En algunos lenguajes, como Java, los IDE emiten una advertencia / pista si haces algo así.