Je veux implémenter des constantes dans un class
, car c'est dans ce sens qu'il est logique de les localiser dans le code.
Jusqu'à présent, j'ai implémenté la solution de contournement suivante avec des méthodes statiques:
class MyClass {
static constant1() { return 33; }
static constant2() { return 2; }
// ...
}
Je sais qu'il est possible de manipuler des prototypes, mais beaucoup le déconseillent.
Existe-t-il un meilleur moyen d'implémenter des constantes dans les classes ES6?
Voici quelques choses que vous pourriez faire:
Exporter un const
à partir du module . Selon votre cas d'utilisation, vous pouvez simplement:
export const constant1 = 33;
Et importez-le du module si nécessaire. Ou, en vous basant sur votre idée de méthode statique, vous pourriez déclarer un static
get accessor :
const constant1 = 33,
constant2 = 2;
class Example {
static get constant1() {
return constant1;
}
static get constant2() {
return constant2;
}
}
De cette façon, vous n'aurez pas besoin de parenthèses:
const one = Example.constant1;
Ensuite, comme vous le dites, étant donné que class
n'est qu'un sucre syntaxique pour une fonction, vous pouvez simplement ajouter une propriété non-inscriptible comme ceci:
class Example {
}
Object.defineProperty(Example, 'constant1', {
value: 33,
writable : false,
enumerable : true,
configurable : false
});
Example.constant1; // 33
Example.constant1 = 15; // TypeError
Ce serait peut-être bien si nous pouvions faire quelque chose comme:
class Example {
static const constant1 = 33;
}
Mais malheureusement, cette syntaxe de propriété de classe ne figure que dans une proposition ES7, et même dans ce cas, cela ne permet pas d'ajouter const
à la propriété.
J'utilise babel
et la syntaxe suivante fonctionne pour moi:
class MyClass {
static constant1 = 33;
static constant2 = {
case1: 1,
case2: 2,
};
// ...
}
MyClass.constant1 === 33
MyClass.constant2.case1 === 1
Veuillez considérer que vous avez besoin du préréglage "stage-0"
.
Pour l'installer:
npm install --save-dev babel-preset-stage-0
// in .babelrc
{
"presets": ["stage-0"]
}
Mise à jour:
utilise actuellement stage-3
class Whatever {
static get MyConst() { return 10; }
}
let a = Whatever.MyConst;
Semble travailler pour moi.
Dans ce document il est écrit:
Il n'y a (intentionnellement) pas de moyen déclaratif direct pour définir des propriétés de données prototypes (autres que des méthodes), des propriétés de classe ou des propriétés d'instance.
Cela signifie que c'est intentionnellement comme ça.
Peut-être que vous pouvez définir une variable dans le constructeur?
constructor(){
this.key = value
}
Il est également possible d'utiliser Object.freeze
sur votre objet classe (es6)/constructeur (es5) pour le rendre immuable:
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
Essayer de modifier la classe vous donnera un échec en douceur (ne jettera aucune erreur, cela n'aura tout simplement aucun effet).
Peut-être juste mettre toutes vos constantes dans un objet gelé?
class MyClass {
constructor() {
this.constants = Object.freeze({
constant1: 33,
constant2: 2,
});
}
static get constant1() {
return this.constants.constant1;
}
doThisAndThat() {
//...
let value = this.constants.constant2;
//...
}
}
Comme https://stackoverflow.com/users/2784136/rodrigo-botti dit, je pense que vous cherchez Object.freeze()
. Voici un exemple de classe avec des statiques immuables:
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;
}
Voici une autre façon de faire
/*
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);
Note - L'ordre est important, vous ne pouvez pas avoir les constantes ci-dessus
Utilisation console.log (Auto.CONSTANT1);
Vous pouvez créer un moyen de définir des constantes statiques sur une classe en utilisant une fonctionnalité impaire des classes ES6. Les statiques étant héritées par leurs sous-classes, vous pouvez effectuer les opérations suivantes:
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);
}
}