Existe-t-il des constantes dans JavaScript?

1132

Existe-t-il un moyen d'utiliser des constantes en JavaScript ?

Sinon, quelle est la pratique courante pour spécifier les variables utilisées comme constantes?

fuentesjr
la source
35
Chromevous permet d'utiliser le mot-clé constpour utiliser des constantes. par exemple const ASDF = "asdf". Cependant, comme il constn'est pas compatible avec plusieurs navigateurs, je m'en tiens généralement à une vardéclaration.
Jacksonkr
20
try{const thing=1091;}catch(e){var thing=1091;}travaux.
Derek 朕 會 功夫
13
Derek: votre try / catch ne limiterait-il pas la portée de la chose que vous déclarez au bloc try / catch? Si vous ne définissez pas correctement la portée, quel est l'intérêt de spécifier constou pas vardu tout?
Coderer
8
@Coderer dans les implémentations actuelles, cela fonctionnera, comme consta la même portée que var, et c'est au niveau de la fonction, pas au niveau du bloc. Si vous suivez la prochaine norme ECMAScript à la place, consta la même portée que let, ce qui signifie qu'elle ne fonctionnera pas.
Jasper
3
@Coderer Mauvaise langue. Les variables en javascript sont la portée de la fonction. Ce n'est pas C.
doug65536

Réponses:

1018

Depuis ES2015 , JavaScript a une notion de const:

const MY_CONSTANT = "some-value";

Cela fonctionnera dans à peu près tous les navigateurs sauf IE 8, 9 et 10 . Certains peuvent également nécessiter un mode strict activé.

Vous pouvez utiliser vardes conventions comme ALL_CAPS pour montrer que certaines valeurs ne doivent pas être modifiées si vous devez prendre en charge des navigateurs plus anciens ou si vous travaillez avec du code hérité:

var MY_CONSTANT = "some-value";
John Millikin
la source
60
Que diriez-vous const x = 24;
Zachary Scott
93
Notez que si vous n'avez pas besoin de compatibilité entre navigateurs (ou si vous êtes en programmation côté serveur dans Rhino ou Node.js), vous pouvez utiliser le constmot - clé. Il est actuellement pris en charge par tous les navigateurs modernes, à l'exception d'IE.
Husky
17
De nos jours (3,5 ans plus tard), vous pouvez utiliser Object.definePropertypour créer des propriétés en lecture seule qui ne peuvent pas non plus être supprimées. Cela fonctionne dans la version actuelle de tous les principaux navigateurs (mais de manière incorrecte dans IE8 ). Voir la réponse par @NotAName
Phrogz
12
@Amyth Ce n'est pas vraiment utile. C'est un guide de style proposé par un seul vendeur. Selon le point de Husky ci-dessus, la compatibilité IE est totalement hors de propos lors de l'écriture de JS côté serveur.
aendrew
32
Étant donné que cette réponse est toujours hautement classée par Google en 2015, il convient de dire qu'elle est désormais obsolète. Le constmot-clé fait désormais officiellement partie de la langue et est pris en charge par tous les navigateurs. Selon statcounter.com, seuls quelques pour cent des internautes utilisent encore d'anciennes versions de navigateur qui ne prenaient pas en charge const.
tristan
310

Essayez-vous de protéger les variables contre les modifications? Si oui, alors vous pouvez utiliser un modèle de module:

var CONFIG = (function() {
     var private = {
         'MY_CONST': '1',
         'ANOTHER_CONST': '2'
     };

     return {
        get: function(name) { return private[name]; }
    };
})();

alert('MY_CONST: ' + CONFIG.get('MY_CONST'));  // 1

CONFIG.MY_CONST = '2';
alert('MY_CONST: ' + CONFIG.get('MY_CONST'));  // 1

CONFIG.private.MY_CONST = '2';                 // error
alert('MY_CONST: ' + CONFIG.get('MY_CONST'));  // 1

En utilisant cette approche, les valeurs ne peuvent pas être modifiées. Mais, vous devez utiliser la méthode get () sur CONFIG :(.

Si vous n'avez pas besoin de protéger strictement la valeur des variables, alors faites comme suggéré et utilisez une convention de TOUS LES CAPS.

Burke
la source
13
Notez que vous pouvez simplement renvoyer une fonction pour la valeur de CONFIG. Cela vous éviterait d'appeler CONFIG.get () tout le temps.
Mathew Byrne,
4
Jolie solution. Mais ces choses devraient être emballées comme une bibliothèque pour ne pas les réinventer dans un nouveau projet.
andrii
82
CONFIG.get = someNewFunctionThatBreaksTheCode... Dans l'ensemble, vous ne pouvez absolument pas appliquer de constantes dans JS (sans mot-clé const). La seule chose que vous pouvez faire est de limiter la visibilité.
Thomas Eding
28
Je crois que privatec'est un futur mot réservé en JavaScript, je ne l'utiliserais pas si j'étais vous.
Zaq
C'est également le modèle de registre.
122

Le constmot-clé se trouve dans le projet ECMAScript 6, mais il ne bénéficie pour l'instant que d'une prise en charge limitée du navigateur: http://kangax.github.io/compat-table/es6/ . La syntaxe est:

const CONSTANT_NAME = 0;
Bill le lézard
la source
13
Si vous essayez d'attribuer une valeur à a const, cela ne génère aucune erreur. L'affectation échoue et la constante a toujours sa valeur d'origine. Il s'agit d'un défaut de conception majeur à mon humble avis, mais tant qu'il existe une convention de dénomination claire et cohérente (comme la populaire ALL_CAPS), je ne pense pas que cela causerait trop de chagrin.
MatrixFrog
6
Gardez un œil sur le support du navigateur ici: kangax.github.io/es5-compat-table/es6/#const
Mark McDonald
6
L'affectation @MatrixFrog générera une erreur avec 'use strict'.
sam
Dois-je définir des constantes dans ALL CAPS?
Lewis
1
@Tresdin C'est une convention de dénomination commune pour définir des constantes dans toutes les majuscules. Rien dans les spécifications linguistiques ne le force, mais ce n'est pas une mauvaise idée. Il rend plus claire votre intention et améliore ainsi la lisibilité du code.
Bill the Lizard
68
"use strict";

var constants = Object.freeze({
    "π": 3.141592653589793 ,
    "e": 2.718281828459045 ,
    "i": Math.sqrt(-1)
});

constants.π;        // -> 3.141592653589793
constants = 3;    // -> TypeError: Cannot assign to read only property 'π' …
constants.π;        // -> 3.141592653589793

delete constants.π; // -> TypeError: Unable to delete property.
constants.π;        // -> 3.141592653589793

Voir Object.freeze . Vous pouvez également l' utiliserconst si vous souhaitez rendre la constantsréférence en lecture seule.

sam
la source
2
Doit mentionner que cela ne fonctionne que sur IE9 + kangax.github.io/compat-table/es5 .
Cordle
Je le ferais, s'il n'avait pas l'implémentation cassée dei
Alnitak
Remarque: cela se comporte de manière similaire à la constdéclaration ES6 , par exemple, les propriétés ne peuvent pas être déclarées ou réaffectées, mais si elles sont de type de données object, elles peuvent être mutées.
le_m
Exactement ce que je cherchais. Vous pouvez également utiliser const constantsau lieu de var constantspour empêcher la réaffectation de la variable.
Jarett Millard
Voir, par exemple, surgélation pour la congélation récursive.
sam
64

IE prend en charge les constantes, par exemple:

<script language="VBScript">
 Const IE_CONST = True
</script>
<script type="text/javascript">
 if (typeof TEST_CONST == 'undefined') {
    const IE_CONST = false;
 }
 alert(IE_CONST);
</script>
C Nagle
la source
50
Garçon, parle de quelque chose qui n'est pas multi-navigateur. . . Toujours +1 pour avoir réfléchi un peu hors des sentiers battus.
Tom
14
VBScript? Qu'est-ce que c'est? ;)
tybro0103
2
Je vote généralement pour une question générale sur les navigateurs croisés, avec une réponse spécifique à IE. Parce que je déteste les gens qui pensent que l'implémentation javascript d'IE est «la seule», et que d'autres doivent être ignorés. Qui utilise d'autres borwsers que IE, btw?
Ant
@Cooluhuru, ce script semble gérer à la fois les navigateurs IE (en utilisant VBScript) et les navigateurs non IE (en utilisant JavaScript const). Pouvez-vous expliquer ce qui ne va pas?
Andrew Grimm
J'ai encore du mal à accepter que les constantes puissent être modifiées.
Norbert Norbertson
59

ECMAScript 5 présente Object.defineProperty:

Object.defineProperty (window,'CONSTANT',{ value : 5, writable: false });

Il est pris en charge dans tous les navigateurs modernes (ainsi que IE ≥ 9).

Voir aussi: Object.defineProperty dans ES5?

Pas un nom
la source
1
Il convient de noter que ce n'est pas comme une constante traditionnelle. Cela vous permettra uniquement de définir une propriété constante (d'un objet non constant). De plus, cela ne génère pas d'erreur et renvoie même la valeur que vous essayez de définir. Il n'écrit tout simplement pas la valeur.
Cory Gross
3
J'ai récemment lu que la tentative d'affectation à une propriété avec writable: false génèrerait en fait une erreur si le code qui effectue l'affectation est interprété sous le mode strict d'ECMAScript 5. Juste une autre raison d'écrire 'use strict'dans votre code.
Cory Gross
6
Vous pouvez réellement omettre writable: falsepuisque c'est la valeur par défaut .
sam
24

Non, pas en général. Firefox implémente constmais je sais qu'IE ne fonctionne pas.


@John pointe vers une pratique de dénomination commune pour les consts qui est utilisée depuis des années dans d'autres langues, je ne vois aucune raison pour laquelle vous ne pourriez pas l'utiliser. Bien sûr, cela ne signifie pas que quelqu'un n'écrira pas de toute façon la valeur de la variable. :)

Jason Bunting
la source
11
Comme tout le monde le sait, si IE ne l'implémente pas, il pourrait tout aussi bien ne pas exister.
Josh Hinman le
3
Malheureusement, et pratiquement parlant - c'est vrai. IE possède une énorme part du marché. Si je possédais une entreprise et que j'utilisais des applications Web en interne, je standardiserais sur FF. Je ne sais pas pourquoi tant de gens se soucient d'IE, ça souffle.
Jason Bunting,
@ Rich: Qui a dit que mon opinion était un fait? Vous avez fait tout à fait l'hypothèse. D'ailleurs, en ce qui me concerne, le fait qu'IE suce est un fait. Vous pouvez avoir vos propres faits, je n'ai pas dit que vous deviez croire les miens. : P Prenez un Xanax ou quelque chose ...
Jason Bunting
@Rich B, oui, c'était juste un commentaire stupide à faire, et croyez-moi, je sais, je fais beaucoup de commentaires stupides. @Jason B. - intéressant, j'ai rencontré ce même problème hier soir. Const a travaillé dans FF mais pas dans IE. Merci pour la clarification
Qui se soucie d'IE? Je ne! FF ou Chrome ou Opera etc ... peuvent être installés presque dans toutes les plateformes OS. De plus, les détaillants d'ordinateurs savent généralement que l'ancienne version d'IE est nulle, ils installent donc souvent (ou même à chaque fois) d'autres navigateurs avant de vendre un ordinateur. J'ai donc décidé que mon application développée ne se soucie pas du tout des navigateurs incompatibles: si les développeurs de navigateurs se soucient du respect des normes, leur produit peut utiliser mon application, sinon, les utilisateurs utiliseront un navigateur différent ... je peux vivre avec; -) Mais Microsoft peut-il vivre en perdant une partie du marché? Non, ils ne peuvent pas alors "Ils" changeront leur politique de développement!
willy wonka
20

En JavaScript, ma préférence est d'utiliser des fonctions pour renvoyer des valeurs constantes.

function MY_CONSTANT() {
   return "some-value";
}


alert(MY_CONSTANT());
MTS
la source
6
Il convient de souligner que cela tombe dans le même problème mentionné dans la réponse de @Burkes (commentaire de @trinithis). `MY_CONSTANT = function () {return" some-other-value "; } le casse. +1 cependant, solution décente et rapide.
Patrick M
13
-1. Cela n'a aucun avantage sur var SOME_NAME = valeur (il est toujours modifiable), est plus de code et nécessite une explication.
mikemaccana
@PatrickM bien qu'il soit vrai que vous pouvez modifier ce type de pseudo-constantes, dans d'autres langages comme par exemple C, sur lesquels vous ne devriez pas pouvoir modifier les constantes, vous pouvez toujours le faire via par exemple des pointeurs. Donc, tant que vous utilisez une approche qui suggère au moins que c'est une constante, c'est bien imo.
rev
20

Les documents Web Mozillas MDN contiennent de bons exemples et des explications sur const. Extrait:

// define MY_FAV as a constant and give it the value 7
const MY_FAV = 7;

// this will throw an error - Uncaught TypeError: Assignment to constant variable.
MY_FAV = 20;

Mais il est triste que IE9 / 10 ne prenne toujours pas en charge const. Et la raison pour laquelle c'est absurde :

Alors, que fait IE9 avec const? Jusqu'à présent, notre décision a été de ne pas l'appuyer. Ce n'est pas encore une fonctionnalité de consensus car il n'a jamais été disponible sur tous les navigateurs.

...

En fin de compte, il semble que la meilleure solution à long terme pour le Web soit de le laisser de côté et d'attendre que les processus de normalisation suivent leur cours.

Ils ne l'implémentent pas parce que d'autres navigateurs ne l'ont pas implémenté correctement?! Vous avez trop peur de l'améliorer? Définitions de normes ou non, une constante est une constante: définie une fois, jamais modifiée.

Et à toutes les idées: chaque fonction peut être écrasée (XSS etc.). Il n'y a donc pas de différence dans varou function(){return}.constest la seule vraie constante.

Mise à jour: IE11 prend en charge const :

IE11 prend en charge les fonctions bien définies et couramment utilisées de la nouvelle norme ECMAScript 6 dont let, const, Map, Set, et WeakMap, ainsi que __proto__pour l' interopérabilité améliorée.

mgutt
la source
25
"il n'a jamais été disponible sur tous les navigateurs". Si vous ne le rendez pas disponible dans IE, il ne le sera jamais dans tous les navigateurs.
km1
la normalisation de la conduite n'est pas pour tout le monde;) - les entreprises viennent et repartent - merci d'avoir cité les cotes dans le bois
Plus
un plus à ce sujet : VBA n'est pas une option consesus dans tous les navigateurs encore et MS supports CONST en VBA - c'est la maîtrise de canaliser les budgets de développement;)
Quicker
17

Si cela ne vous dérange pas d'utiliser des fonctions:

var constant = function(val) {
   return function() {
        return val;
    }
}

Cette approche vous donne des fonctions au lieu de variables régulières, mais elle garantit * que personne ne peut modifier la valeur une fois qu'elle est définie.

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

Personnellement, je trouve cela plutôt agréable, surtout après s'être habitué à ce modèle des observables à élimination directe.

* Sauf si quelqu'un a redéfini la fonction constantavant de l'appeler

hasen
la source
1
underscore.js implémente une fonction constante identique à ce code.
Upperstage
Simple, concis et répond à l'esprit de la question d'OP. Cela aurait dû recevoir plus de votes positifs.
Mac
3
Cela n'a jamais vraiment fonctionné pour moi. Même si la fermeture la rend immuable, la variable à laquelle vous l'affectez peut toujours être remplacée. Ex: a = constant(10); a(10); // 10suivi de a = constant(25); a(); //25, aucune erreur ou avertissement donné, aucune indication que votre constante a été cassée.
Patrick M
Si je valeur Réattribuer pour aensuite les changements de valeur aux nouveaux
Saurabh Sharma
17

avec la "nouvelle" API d'objet, vous pouvez faire quelque chose comme ceci:

var obj = {};
Object.defineProperty(obj, 'CONSTANT', {
  configurable: false
  enumerable: true,
  writable: false,
  value: "your constant value"
});

jetez un oeil à cela sur le MDN Mozilla pour plus de détails. Ce n'est pas une variable de premier niveau, car elle est attachée à un objet, mais si vous avez une portée, n'importe quoi, vous pouvez la joindre à cela. thisdevrait également fonctionner. Ainsi, par exemple, faire cela dans la portée globale déclarera une valeur pseudo constante sur la fenêtre (ce qui est vraiment une mauvaise idée, vous ne devriez pas déclarer les vars globaux sans précaution)

Object.defineProperty(this, 'constant', {
  enumerable: true, 
  writable: false, 
  value: 7, 
  configurable: false
});

> constant
=> 7
> constant = 5
=> 7

note: l'affectation vous rendra la valeur assignée dans la console, mais la valeur de la variable ne changera pas

tenshou
la source
Ne fonctionne pas dans safari et dans mozilla si vous exécutez à nouveau l'instruction define - avec une valeur différente - il réaffectera la valeur.
Akshay
2
Ne fonctionne pas en safari, non pris en charge en safari. Pas le même. Et il devrait lancer une 'TypeError non capturée: ne peut pas redéfinir la propriété: <nom de la propriété ici>' si vous essayez cela. soit vous le faites mal, soit votre ff l'a implémenté incorrectement. Je suppose que c'est un mélange des deux.
tenshou
14

Groupez les constantes en structures lorsque cela est possible:

Exemple, dans mon projet de jeu actuel, j'ai utilisé ci-dessous:

var CONST_WILD_TYPES = {
    REGULAR: 'REGULAR',
    EXPANDING: 'EXPANDING',
    STICKY: 'STICKY',
    SHIFTING: 'SHIFTING'
};

Affectation:

var wildType = CONST_WILD_TYPES.REGULAR;

Comparaison:

if (wildType === CONST_WILD_TYPES.REGULAR) {
    // do something here
}

Plus récemment, j'utilise, à titre de comparaison:

switch (wildType) {
    case CONST_WILD_TYPES.REGULAR:
        // do something here
        break;
    case CONST_WILD_TYPES.EXPANDING:
        // do something here
        break;
}

IE11 est avec la nouvelle norme ES6 qui a la déclaration «const».
Ci-dessus fonctionne dans les navigateurs précédents comme IE8, IE9 et IE10.

Manohar Reddy Poreddy
la source
12

Vous pouvez facilement équiper votre script d'un mécanisme de constantes qui peuvent être définies mais pas modifiées. Une tentative de modification entraînera une erreur.

/* author Keith Evetts 2009 License: LGPL  
anonymous function sets up:  
global function SETCONST (String name, mixed value)  
global function CONST (String name)  
constants once set may not be altered - console error is generated  
they are retrieved as CONST(name)  
the object holding the constants is private and cannot be accessed from the outer script directly, only through the setter and getter provided  
*/

(function(){  
  var constants = {};  
  self.SETCONST = function(name,value) {  
      if (typeof name !== 'string') { throw new Error('constant name is not a string'); }  
      if (!value) { throw new Error(' no value supplied for constant ' + name); }  
      else if ((name in constants) ) { throw new Error('constant ' + name + ' is already defined'); }   
      else {   
          constants[name] = value;   
          return true;  
    }    
  };  
  self.CONST = function(name) {  
      if (typeof name !== 'string') { throw new Error('constant name is not a string'); }  
      if ( name in constants ) { return constants[name]; }    
      else { throw new Error('constant ' + name + ' has not been defined'); }  
  };  
}())  


// -------------  demo ----------------------------  
SETCONST( 'VAT', 0.175 );  
alert( CONST('VAT') );


//try to alter the value of VAT  
try{  
  SETCONST( 'VAT', 0.22 );  
} catch ( exc )  {  
   alert (exc.message);  
}  
//check old value of VAT remains  
alert( CONST('VAT') );  


// try to get at constants object directly  
constants['DODO'] = "dead bird";  // error  
Keith
la source
12

Oubliez IE et utilisez le constmot - clé.

Derek 朕 會 功夫
la source
9
travaille pour moi! mais ensuite j'écris une extension chrome, donc je sais que je suis sur un navigateur sain d'esprit ...
yoyo
1
@yoyo meilleure partie sur l'écriture d'extensions et d'extensions - pas de support multi-navigateur!
Ian
1
@Ian Bienvenue en 2019, l'incohérence entre les navigateurs a presque disparu :)
Fusseldieb
9

Pourtant, il n'y a pas de moyen exact prédéfini pour tous les navigateurs, vous pouvez y parvenir en contrôlant la portée des variables comme indiqué dans les autres réponses.

Mais je proposerai d'utiliser l'espace de nom pour faire la distinction avec les autres variables. cela réduira le risque de collision au minimum des autres variables.

Espacement de noms approprié comme

var iw_constant={
     name:'sudhanshu',
     age:'23'
     //all varibale come like this
}

donc tout en l'utilisant sera iw_constant.nameouiw_constant.age

Vous pouvez également bloquer l'ajout de toute nouvelle clé ou la modification d'une clé dans iw_constant à l'aide de la méthode Object.freeze. Cependant, ce n'est pas pris en charge sur le navigateur hérité.

ex:

Object.freeze(iw_constant);

Pour les anciens navigateurs, vous pouvez utiliser polyfill pour la méthode de gel.


Si vous êtes d'accord avec l'appel de la fonction suivante, c'est la meilleure façon de traverser le navigateur pour définir la constante. Portée de votre objet dans une fonction auto-exécutable et retour d'une fonction get pour vos constantes ex:

var iw_constant= (function(){
       var allConstant={
             name:'sudhanshu',
             age:'23'
             //all varibale come like this

       };

       return function(key){
          allConstant[key];
       }
    };

// pour obtenir la valeur, utilisez iw_constant('name')ouiw_constant('age')


** Dans les deux exemples, vous devez être très prudent sur l'espacement des noms afin que votre objet ou fonction ne soit pas remplacé par une autre bibliothèque (si l'objet ou la fonction lui-même sera remplacé, toute votre constante ira)

Sudhanshu Yadav
la source
7

Pendant un certain temps, j'ai spécifié des «constantes» (qui n'étaient toujours pas réellement des constantes) dans les littéraux d'objet transmis aux with()instructions. Je pensais que c'était si intelligent. Voici un exemple:

with ({
    MY_CONST : 'some really important value'
}) {
    alert(MY_CONST);
}

Dans le passé, j'ai également créé un CONST espace de noms où je mettrais toutes mes constantes. Encore une fois, avec les frais généraux. Sheesh.

Maintenant, je fais juste var MY_CONST = 'whatever';pour BAISER .

Andrew Hedges
la source
16
S'il y a quelque chose de plus mauvais que l'eval, c'est certainement with.
NikiC
4
eval est très mal! Il a incendié ma maison une fois!
W3Geek
6

Mon avis (ne fonctionne qu'avec des objets).

var constants = (function(){
  var a = 9;

  //GLOBAL CONSTANT (through "return")
  window.__defineGetter__("GCONST", function(){
    return a;
  });

  //LOCAL CONSTANT
  return {
    get CONST(){
      return a;
    }
  }
})();

constants.CONST = 8; //9
alert(constants.CONST); //9

Essayer! Mais comprenez - c'est un objet, mais pas une simple variable.

Essayez aussi juste:

const a = 9;
user1635543
la source
5

Moi aussi, j'ai eu un problème avec ça. Et après un certain temps à chercher la réponse et à regarder toutes les réponses de tout le monde, je pense que j'ai trouvé une solution viable à cela.

Il semble que la plupart des réponses que j'ai rencontrées utilisent des fonctions pour contenir les constantes. Comme de nombreux utilisateurs des nombreux forums le mentionnent, les fonctions peuvent être facilement écrasées par les utilisateurs côté client. J'ai été intrigué par la réponse de Keith Evetts selon laquelle l'objet constantes n'est pas accessible par l'extérieur, mais uniquement par les fonctions à l'intérieur.

J'ai donc trouvé cette solution:

Mettez tout à l'intérieur d'une fonction anonyme afin que les variables, les objets, etc. ne puissent pas être modifiés par le client. Masquez également les fonctions «réelles» en faisant en sorte que d'autres fonctions appellent les fonctions «réelles» de l'intérieur. J'ai également pensé à utiliser des fonctions pour vérifier si une fonction a été modifiée par un utilisateur côté client. Si les fonctions ont été modifiées, modifiez-les à nouveau à l'aide de variables qui sont «protégées» à l'intérieur et ne peuvent pas être modifiées.

/*Tested in: IE 9.0.8; Firefox 14.0.1; Chrome 20.0.1180.60 m; Not Tested in Safari*/

(function(){
  /*The two functions _define and _access are from Keith Evetts 2009 License: LGPL (SETCONST and CONST).
    They're the same just as he did them, the only things I changed are the variable names and the text
    of the error messages.
  */

  //object literal to hold the constants
  var j = {};

  /*Global function _define(String h, mixed m). I named it define to mimic the way PHP 'defines' constants.
    The argument 'h' is the name of the const and has to be a string, 'm' is the value of the const and has
    to exist. If there is already a property with the same name in the object holder, then we throw an error.
    If not, we add the property and set the value to it. This is a 'hidden' function and the user doesn't
    see any of your coding call this function. You call the _makeDef() in your code and that function calls
    this function.    -    You can change the error messages to whatever you want them to say.
  */
  self._define = function(h,m) {
      if (typeof h !== 'string') { throw new Error('I don\'t know what to do.'); }
      if (!m) { throw new Error('I don\'t know what to do.'); }
      else if ((h in j) ) { throw new Error('We have a problem!'); }
      else {
          j[h] = m;
          return true;
    }
  };

  /*Global function _makeDef(String t, mixed y). I named it makeDef because we 'make the define' with this
    function. The argument 't' is the name of the const and doesn't need to be all caps because I set it
    to upper case within the function, 'y' is the value of the value of the const and has to exist. I
    make different variables to make it harder for a user to figure out whats going on. We then call the
    _define function with the two new variables. You call this function in your code to set the constant.
    You can change the error message to whatever you want it to say.
  */
  self._makeDef = function(t, y) {
      if(!y) { throw new Error('I don\'t know what to do.'); return false; }
      q = t.toUpperCase();
      w = y;
      _define(q, w);
  };

  /*Global function _getDef(String s). I named it getDef because we 'get the define' with this function. The
    argument 's' is the name of the const and doesn't need to be all capse because I set it to upper case
    within the function. I make a different variable to make it harder for a user to figure out whats going
    on. The function returns the _access function call. I pass the new variable and the original string
    along to the _access function. I do this because if a user is trying to get the value of something, if
    there is an error the argument doesn't get displayed with upper case in the error message. You call this
    function in your code to get the constant.
  */
  self._getDef = function(s) {
      z = s.toUpperCase();
      return _access(z, s);
  };

  /*Global function _access(String g, String f). I named it access because we 'access' the constant through
    this function. The argument 'g' is the name of the const and its all upper case, 'f' is also the name
    of the const, but its the original string that was passed to the _getDef() function. If there is an
    error, the original string, 'f', is displayed. This makes it harder for a user to figure out how the
    constants are being stored. If there is a property with the same name in the object holder, we return
    the constant value. If not, we check if the 'f' variable exists, if not, set it to the value of 'g' and
    throw an error. This is a 'hidden' function and the user doesn't see any of your coding call this
    function. You call the _getDef() function in your code and that function calls this function.
    You can change the error messages to whatever you want them to say.
  */
  self._access = function(g, f) {
      if (typeof g !== 'string') { throw new Error('I don\'t know what to do.'); }
      if ( g in j ) { return j[g]; }
      else { if(!f) { f = g; } throw new Error('I don\'t know what to do. I have no idea what \''+f+'\' is.'); }
  };

  /*The four variables below are private and cannot be accessed from the outside script except for the
    functions inside this anonymous function. These variables are strings of the four above functions and
    will be used by the all-dreaded eval() function to set them back to their original if any of them should
    be changed by a user trying to hack your code.
  */
  var _define_func_string = "function(h,m) {"+"      if (typeof h !== 'string') { throw new Error('I don\\'t know what to do.'); }"+"      if (!m) { throw new Error('I don\\'t know what to do.'); }"+"      else if ((h in j) ) { throw new Error('We have a problem!'); }"+"      else {"+"          j[h] = m;"+"          return true;"+"    }"+"  }";
  var _makeDef_func_string = "function(t, y) {"+"      if(!y) { throw new Error('I don\\'t know what to do.'); return false; }"+"      q = t.toUpperCase();"+"      w = y;"+"      _define(q, w);"+"  }";
  var _getDef_func_string = "function(s) {"+"      z = s.toUpperCase();"+"      return _access(z, s);"+"  }";
  var _access_func_string = "function(g, f) {"+"      if (typeof g !== 'string') { throw new Error('I don\\'t know what to do.'); }"+"      if ( g in j ) { return j[g]; }"+"      else { if(!f) { f = g; } throw new Error('I don\\'t know what to do. I have no idea what \\''+f+'\\' is.'); }"+"  }";

  /*Global function _doFunctionCheck(String u). I named it doFunctionCheck because we're 'checking the functions'
    The argument 'u' is the name of any of the four above function names you want to check. This function will
    check if a specific line of code is inside a given function. If it is, then we do nothing, if not, then
    we use the eval() function to set the function back to its original coding using the function string
    variables above. This function will also throw an error depending upon the doError variable being set to true
    This is a 'hidden' function and the user doesn't see any of your coding call this function. You call the
    doCodeCheck() function and that function calls this function.    -    You can change the error messages to
    whatever you want them to say.
  */
  self._doFunctionCheck = function(u) {
      var errMsg = 'We have a BIG problem! You\'ve changed my code.';
      var doError = true;
      d = u;
      switch(d.toLowerCase())
      {
           case "_getdef":
               if(_getDef.toString().indexOf("z = s.toUpperCase();") != -1) { /*do nothing*/ }
               else { eval("_getDef = "+_getDef_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           case "_makedef":
               if(_makeDef.toString().indexOf("q = t.toUpperCase();") != -1) { /*do nothing*/ }
               else { eval("_makeDef = "+_makeDef_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           case "_define":
               if(_define.toString().indexOf("else if((h in j) ) {") != -1) { /*do nothing*/ }
               else { eval("_define = "+_define_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           case "_access":
               if(_access.toString().indexOf("else { if(!f) { f = g; }") != -1) { /*do nothing*/ }
               else { eval("_access = "+_access_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           default:
                if(doError === true) { throw new Error('I don\'t know what to do.'); }
      }
  };

  /*Global function _doCodeCheck(String v). I named it doCodeCheck because we're 'doing a code check'. The argument
    'v' is the name of one of the first four functions in this script that you want to check. I make a different
    variable to make it harder for a user to figure out whats going on. You call this function in your code to check
    if any of the functions has been changed by the user.
  */
  self._doCodeCheck = function(v) {
      l = v;
      _doFunctionCheck(l);
  };
}())

Il semble également que la sécurité soit vraiment un problème et il n'y a aucun moyen de «cacher» votre programmation du côté client. Une bonne idée pour moi est de compresser votre code afin qu'il soit vraiment difficile pour quiconque, y compris vous, le programmeur, de le lire et de le comprendre. Il existe un site sur lequel vous pouvez vous rendre: http://javascriptcompressor.com/ . (Ce n'est pas mon site, ne vous inquiétez pas, je ne fais pas de publicité.) C'est un site qui vous permettra de compresser et d'obscurcir du code Javascript gratuitement.

  1. Copiez tout le code du script ci-dessus et collez-le dans la zone de texte supérieure de la page javascriptcompressor.com.
  2. Cochez la case Base62 encode, cochez la case Shrink Variables.
  3. Appuyez sur le bouton Compress.
  4. Collez et enregistrez le tout dans un fichier .js et ajoutez-le à votre page en tête de votre page.
Steven Kapaun
la source
C'est une bonne solution qui pourrait être bien présentée comme une bibliothèque à inclure. Mais je n'aime pas le nom de vos variables dans ce code. Pourquoi supprimer les noms descriptifs comme "nom" et "valeur" tels qu'ils sont utilisés dans le code de Keith? Problème mineur, mais quand même.
Cordle
5

Cela montre clairement la nécessité d'un mot-clé const inter-navigateur standardisé.

Mais pour l'instant:

var myconst = value;

ou

Object['myconst'] = value;

Les deux semblent suffisants et tout le reste, c'est comme tirer une mouche avec un bazooka.

codemuncher
la source
prenez le bon vieux var myconst = value; et pour le débogage, utilisez du code de débogage supplémentaire ... - fonctionne comme un fou tant que tous les navigateurs ne prennent pas en charge const
Quicker
4

J'utilise à la constplace de vardans mes scripts Greasemonkey, mais c'est parce qu'ils ne fonctionneront que sur Firefox ... La
convention de nom peut aussi être la voie à suivre (je fais les deux!).

PhiLho
la source
4

En JavaScript, ma pratique a été d'éviter autant que possible les constantes et d'utiliser des chaînes à la place. Des problèmes avec les constantes apparaissent lorsque vous souhaitez exposer vos constantes au monde extérieur:

Par exemple, on pourrait implémenter l'API Date suivante:

date.add(5, MyModule.Date.DAY).add(12, MyModule.Date.HOUR)

Mais il est beaucoup plus court et plus naturel d'écrire simplement:

date.add(5, "days").add(12, "hours")

De cette façon, les "jours" et les "heures" agissent vraiment comme des constantes, car vous ne pouvez pas changer de l'extérieur le nombre de secondes que "les heures" représentent. Mais il est facile d'écraserMyModule.Date.HOUR .

Ce type d'approche facilitera également le débogage. Si Firebug vous dit action === 18qu'il est assez difficile de comprendre ce que cela signifie, mais quand vous voyez, action === "save"c'est immédiatement clair.

René Saarsoo
la source
Il est malheureusement assez facile de faire des fautes d'orthographe - par exemple "Hours"au lieu de "hours"- mais un IDE peut vous faire savoir très tôt que cela Date.Hoursn'est pas défini.
le_m
4

D'accord, c'est moche, mais cela me donne une constante dans Firefox et Chrome, une constante inconstante (WTF?) Dans Safari et Opera, et une variable dans IE.

Bien sûr, eval () est mauvais, mais sans lui, IE lance une erreur, empêchant les scripts de s'exécuter.

Safari et Opera prennent en charge le mot clé const, mais vous pouvez modifier la valeur de const .

Dans cet exemple, le code côté serveur écrit JavaScript dans la page, en remplaçant {0} par une valeur.

try{
    // i can haz const?
    eval("const FOO='{0}';");
    // for reals?
    var original=FOO;
    try{
        FOO='?NO!';
    }catch(err1){
        // no err from Firefox/Chrome - fails silently
        alert('err1 '+err1);
    }
    alert('const '+FOO);
    if(FOO=='?NO!'){
        // changed in Sf/Op - set back to original value
        FOO=original;
    }
}catch(err2){
    // IE fail
    alert('err2 '+err2);
    // set var (no var keyword - Chrome/Firefox complain about redefining const)
    FOO='{0}';
    alert('var '+FOO);
}
alert('FOO '+FOO);

À quoi cela sert-il? Pas grand-chose, car ce n'est pas multi-navigateur. Au mieux, peut-être un peu de tranquillité d'esprit qu'au moins certains navigateurs ne laisseront pas les bookmarklets ou les scripts tiers modifier la valeur.

Testé avec Firefox 2, 3, 3.6, 4, Iron 8, Chrome 10, 12, Opera 11, Safari 5, IE 6, 9.

Webveloper
la source
1
J'adore ce code! Laid comme diable, mais un bon test pour le soutien const. =)
Stein G. Strindhaug
1
quelque peu drôle, ey ​​- combien de lignes pouvez-vous taper pour déclarer un const?
Quicker
4

Si cela vaut la peine d'être mentionné, vous pouvez définir des constantes angulaires en utilisant$provide.constant()

angularApp.constant('YOUR_CONSTANT', 'value');
Muhammad Reda
la source
? ... et vous pouvez utiliser const dans VBA ... xbrowser ... ups ...;)
Quicker
OP pose des questions sur javascript, la réponse porte sur un cadre JS spécifique et très avisé. Pratiquement hors sujet.
Rounce
2
@rounce: réponses hors sujet sont encore des réponses, ne drapeau eux pas une réponse mais downvote et vote pour supprimer la place. Voir Comment utiliser correctement l'indicateur «Pas une réponse»?
Kevin Guan
@KevinGuan Noté, fera l'affaire à l'avenir.
Rounce
4

Une version améliorée de la réponse de Burke qui vous permet de faire à la CONFIG.MY_CONSTplace de CONFIG.get('MY_CONST').

Il nécessite IE9 + ou un véritable navigateur Web.

var CONFIG = (function() {
    var constants = {
        'MY_CONST': 1,
        'ANOTHER_CONST': 2
    };

    var result = {};
    for (var n in constants)
        if (constants.hasOwnProperty(n))
            Object.defineProperty(result, n, { value: constants[n] });

    return result;
}());

* Les propriétés sont en lecture seule, uniquement si les valeurs initiales sont immuables.

Şafak Gür
la source
4

JavaScript ES6 (re) a introduit le constmot clé qui est pris en charge dans tous les principaux navigateurs .

Les variables déclarées via constne peuvent pas être déclarées ou réaffectées.

En dehors de cela, constse comporte de manière similaire à let.

Il se comporte comme prévu pour les types de données primitifs (booléen, nul, non défini, nombre, chaîne, symbole):

const x = 1;
x = 2;
console.log(x); // 1 ...as expected, re-assigning fails

Attention: soyez conscient des pièges concernant les objets:

const o = {x: 1};
o = {x: 2};
console.log(o); // {x: 1} ...as expected, re-assigning fails

o.x = 2;
console.log(o); // {x: 2} !!! const does not make objects immutable!

const a = [];
a = [1];
console.log(a); // 1 ...as expected, re-assigning fails

a.push(1);
console.log(a); // [1] !!! const does not make objects immutable

Si vous avez vraiment besoin d'un objet immuable et absolument constant: utilisez simplement const ALL_CAPSpour clarifier votre intention. De toute constfaçon, c'est une bonne convention à suivre pour toutes les déclarations, alors comptez-y.

le_m
la source
Depuis IE11 uniquement :-(
lun
3

Une autre alternative est quelque chose comme:

var constants = {
      MY_CONSTANT : "myconstant",
      SOMETHING_ELSE : 123
    }
  , constantMap = new function ConstantMap() {};

for(var c in constants) {
  !function(cKey) {
    Object.defineProperty(constantMap, cKey, {
      enumerable : true,
      get : function(name) { return constants[cKey]; }
    })
  }(c);
}

Alors simplement: var foo = constantMap.MY_CONSTANT

Si vous le faisiez, constantMap.MY_CONSTANT = "bar"cela n'aurait aucun effet car nous essayons d'utiliser un opérateur d'affectation avec un getter, donc constantMap.MY_CONSTANT === "myconstant"cela resterait vrai.

rebondir
la source
3

en Javascript existe déjà des constantes . Vous définissez une constante comme celle-ci:

const name1 = value;

Cela ne peut pas changer par une réaffectation.

Erik Lucio
la source
Par le lien dans la réponse, il s'agit d'une fonctionnalité expérimentale et doit être utilisée avec prudence.
Johnie Karr
Bien sûr, je suis d'accord avec toi. Mais dans les dernières versions des navigateurs, cela fonctionne.
Erik Lucio
3

Le mot-clé «const» a été proposé précédemment et il est maintenant officiellement inclus dans ES6. En utilisant le mot clé const, vous pouvez passer une valeur / chaîne qui agira comme une chaîne immuable.

Ritumoni Sharma
la source
2

L'introduction de constantes dans JavaScript est au mieux un hack.

Une bonne façon de rendre des valeurs persistantes et accessibles à tous en JavaScript serait de déclarer un objet littéral avec quelques propriétés "en lecture seule" comme ceci:

            my={get constant1(){return "constant 1"},
                get constant2(){return "constant 2"},
                get constant3(){return "constant 3"},
                get constantN(){return "constant N"}
                }

vous aurez toutes vos constantes regroupées dans un seul objet accessoire "mon" où vous pourrez rechercher vos valeurs stockées ou toute autre chose que vous auriez pu décider d'y mettre d'ailleurs. Maintenant, testons si cela fonctionne:

           my.constant1; >> "constant 1" 
           my.constant1 = "new constant 1";
           my.constant1; >> "constant 1" 

Comme nous pouvons le voir, la propriété "my.constant1" a conservé sa valeur d'origine. Vous vous êtes fait de belles constantes temporaires "vertes" ...

Mais bien sûr, cela ne vous empêchera de modifier, d'altérer, d'annuler ou de vider accidentellement la valeur constante de votre propriété avec un accès direct comme dans l'exemple donné.

Sinon, je pense toujours que les constantes sont pour les nuls. Et je pense toujours qu'échanger votre grande liberté contre un petit coin de sécurité trompeuse est le pire commerce possible.

Bill le lézard
la source
2

Rhino.jsmet consten œuvre en plus de ce qui a été mentionné ci-dessus.

isomorphismes
la source