web-dev-qa-db-fra.com

Déclarer des constantes statiques dans les classes ES6?

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?

263
Jérôme Verstrynge

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 staticget 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;

Babel REPL Exemple

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é.

328
CodingIntrigue

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

23
borracciaBlu
class Whatever {
    static get MyConst() { return 10; }
}

let a = Whatever.MyConst;

Semble travailler pour moi.

19
Benny Jobigan

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
}
13
DevAlien

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).

10
rodrigo.botti

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;
        //...
    }
}
5
aRIEL

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;
}
4
jeffwtribble

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);

1
user3871424

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);
  }
}
1
TbWill4321