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; // 1
Mirando 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í
PropertyMethodDefinition
se 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=true
a 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
Function
objeto, no cualquier otro valor como aNumber
oObject
).Aún puede especificarlos utilizando los especificadores de propiedad del constructor ECMAScript tradicionales:
class Agent { } Agent.CIRCLE = 1; Agent.SQUARE = 2; ...
fuente
class
sintaxis de ES6 es simplemente azúcar sintáctica para las funciones y prototipos de constructores JS tradicionales de todos modos.enum
).class
sintaxis 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 losclass
mé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; // Undefined
Si 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); // false
fuente
static
campo 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í.