javascript - estatica - ¿Declarando constantes estáticas en las clases de ES6?
clase estatica javascript (9)
Quiero implementar constantes en una
class
, porque ahí es donde tiene sentido ubicarlas en el código.
Hasta ahora, he estado implementando la siguiente solución con métodos estáticos:
class MyClass {
static constant1() { return 33; }
static constant2() { return 2; }
// ...
}
Sé que existe la posibilidad de jugar con los prototipos, pero muchos recomiendan no hacerlo.
¿Hay una mejor manera de implementar constantes en las clases de ES6?
¿Quizás solo ponga todas sus constantes en un objeto congelado?
class MyClass {
constructor() {
this.constants = Object.freeze({
constant1: 33,
constant2: 2,
});
}
static get constant1() {
return this.constants.constant1;
}
doThisAndThat() {
//...
let value = this.constants.constant2;
//...
}
}
Aquí hay algunas cosas que puedes hacer:
Exportar una
const
desde el
módulo
.
Dependiendo de su caso de uso, podría simplemente:
export const constant1 = 33;
E importe eso desde el módulo cuando sea necesario.
O, basándose en su idea de método estático, podría declarar un
get get
static
:
const constant1 = 33,
constant2 = 2;
class Example {
static get constant1() {
return constant1;
}
static get constant2() {
return constant2;
}
}
De esa manera, no necesitarás paréntesis:
const one = Example.constant1;
Luego, como usted dice, dado que una
class
es solo azúcar sintáctica para una función, puede agregar una propiedad no editable como esta:
class Example {
}
Object.defineProperty(Example, ''constant1'', {
value: 33,
writable : false,
enumerable : true,
configurable : false
});
Example.constant1; // 33
Example.constant1 = 15; // TypeError
Puede ser bueno si pudiéramos hacer algo como:
class Example {
static const constant1 = 33;
}
Pero desafortunadamente, esta
sintaxis de propiedad de clase
solo está en una propuesta de ES7, e incluso entonces no permitirá agregar
const
a la propiedad.
Aquí hay una manera más que puedes hacer
/*
one more way of declaring constants in a class,
Note - the constants have to be declared after the class is defined
*/
class Auto{
//other methods
}
Auto.CONSTANT1 = "const1";
Auto.CONSTANT2 = "const2";
console.log(Auto.CONSTANT1)
console.log(Auto.CONSTANT2);
Nota: el orden es importante, no puede tener las constantes anteriores
Uso console.log (Auto.CONSTANT1);
Como dijo
, creo que estás buscando
Object.freeze()
.
Aquí hay un ejemplo de una clase con estática inmutable:
class User {
constructor(username, age) {
if (age < User.minimumAge) {
throw new Error(''You are too young to be here!'');
}
this.username = username;
this.age = age;
this.state = ''active'';
}
}
User.minimumAge = 16;
User.validStates = [''active'', ''inactive'', ''archived''];
deepFreeze(User);
function deepFreeze(value) {
if (typeof value === ''object'' && value !== null) {
Object.freeze(value);
Object.getOwnPropertyNames(value).forEach(property => {
deepFreeze(value[property]);
});
}
return value;
}
En este documento dice:
No existe (intencionalmente) una forma declarativa directa para definir propiedades de datos de prototipo (que no sean métodos) propiedades de clase o propiedad de instancia
Esto significa que es intencionalmente así.
¿Quizás puedas definir una variable en el constructor?
constructor(){
this.key = value
}
Estoy usando
babel
y la siguiente sintaxis está funcionando para mí:
class MyClass {
static constant1 = 33;
static constant2 = {
case1: 1,
case2: 2,
};
// ...
}
MyClass.constant1 === 33
MyClass.constant2.case1 === 1
Tenga en cuenta que necesita el preajuste
"stage-0"
.
Para instalarlo:
npm install --save-dev babel-preset-stage-0
// in .babelrc
{
"presets": ["stage-0"]
}
Actualizar:
Actualmente uso
stage-3
Puede crear una forma de definir constantes estáticas en una clase utilizando una característica extraña de las clases ES6. Dado que las subclases heredan las estadísticas, puede hacer lo siguiente:
const withConsts = (map, BaseClass = Object) => {
class ConstClass extends BaseClass { }
Object.keys(map).forEach(key => {
Object.defineProperty(ConstClass, key, {
value: map[key],
writable : false,
enumerable : true,
configurable : false
});
});
return ConstClass;
};
class MyClass extends withConsts({ MY_CONST: ''this is defined'' }) {
foo() {
console.log(MyClass.MY_CONST);
}
}
También es posible usar
Object.freeze
en su objeto class (es6) / constructor function (es5) para hacerlo inmutable:
class MyConstants {}
MyConstants.staticValue = 3;
MyConstants.staticMethod = function() {
return 4;
}
Object.freeze(MyConstants);
// after the freeze, any attempts of altering the MyConstants class will have no result
// (either trying to alter, add or delete a property)
MyConstants.staticValue === 3; // true
MyConstants.staticValue = 55; // will have no effect
MyConstants.staticValue === 3; // true
MyConstants.otherStaticValue = "other" // will have no effect
MyConstants.otherStaticValue === undefined // true
delete MyConstants.staticMethod // false
typeof(MyConstants.staticMethod) === "function" // true
Intentar alterar la clase te dará un fallo suave (no arrojará ningún error, simplemente no tendrá ningún efecto).
class Whatever {
static get MyConst() { return 10; }
}
let a = Whatever.MyConst;
Parece funcionar para mi.