Ci sono costanti in JavaScript?

C’è un modo per usare le costanti in JavaScript?

In caso contrario, qual è la pratica comune per specificare le variabili che vengono utilizzate come costanti?

Dal momento che ES2015 , JavaScript ha una nozione di const :

 const MY_CONSTANT = "some-value"; 

Questo funzionerà in quasi tutti i browser tranne IE 8, 9 e 10 . Alcuni potrebbero anche aver bisogno della modalità rigorosa abilitata.

Puoi utilizzare var con convenzioni come ALL_CAPS per mostrare che determinati valori non devono essere modificati se devi supportare browser più vecchi o se stai lavorando con codice legacy:

 var MY_CONSTANT = "some-value"; 

Stai cercando di proteggere le variabili contro le modifiche? Se è così, allora puoi usare un modello di modulo:

 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 

Utilizzando questo approccio, i valori non possono essere modificati. Ma, devi usare il metodo get () su CONFIG :(.

Se non è necessario proteggere rigorosamente il valore delle variabili, basta fare come suggerito e utilizzare una convenzione di ALL CAPS.

La parola chiave const trova nella bozza ECMAScript 6, ma finora gode solo di un’infarinatura del supporto del browser: http://kangax.github.io/compat-table/es6/ . La syntax è:

 const CONSTANT_NAME = 0; 
 "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 

Vedi Object.freeze . È ansible utilizzare const se si desidera rendere le constants riferimento anche in sola lettura.

IE supporta le costanti, ad esempio, ad esempio:

   

ECMAScript 5 introduce Object.defineProperty :

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

È supportato in tutti i browser moderni (così come IE ≥ 9).

Vedi anche: Object.defineProperty in ES5?

No, non in generale. Firefox implementa const ma so che IE no.


@John fa riferimento a una pratica di denominazione comune per i consisti che è stata usata per anni in altre lingue, non vedo ragioni per cui non si possa usare quello. Ovviamente questo non significa che qualcuno non scriverà comunque il valore della variabile. 🙂

Mozilla MDN Web Doc contiene buoni esempi e spiegazioni su const . Estratto:

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

Ma è triste che IE9 / 10 non supporti ancora const . E la ragione è assurda :

Quindi, cosa sta facendo IE9 con const? Finora, la nostra decisione è stata quella di non supportarlo. Non è ancora una funzionalità di consenso in quanto non è mai stato disponibile su tutti i browser.

Alla fine, sembra che la migliore soluzione a lungo termine per il web sia quella di lasciarlo fuori e aspettare che i processi di standardizzazione seguano il loro corso.

Non lo implementano perché altri browser non l’hanno implementato correttamente ?! Troppa paura di renderlo migliore? Definizioni standard o no, una costante è una costante: imposta una volta, non cambia mai.

E a tutte le idee: ogni funzione può essere sovrascritta (XSS ecc.). Quindi non c’è differenza in var o function(){return} . const è l’unica vera costante.

Aggiornamento: IE11 supporta const :

IE11 include il supporto per le funzioni ben definite e comunemente utilizzate dello standard emergente ECMAScript 6 tra cui let, const , Map , Set e WeakMap , nonché __proto__ per una migliore interoperabilità.

In JavaScript, la mia preferenza è usare le funzioni per restituire valori costanti.

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

Se non ti dispiace usare le funzioni:

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

Questo approccio fornisce funzioni anziché variabili regolari, ma garantisce * che nessuno può modificare il valore una volta impostato.

 a = constant(10); a(); // 10 b = constant(20); b(); // 20 

Personalmente trovo questo piuttosto piacevole, specialmente dopo essermi abituato a questo schema da osservabili a eliminazione diretta.

* A meno che qualcuno non abbia ridefinito la funzione constant prima di chiamarla

con il “nuovo” Object api puoi fare qualcosa del genere:

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

dai un’occhiata a questo su Mozilla MDN per ulteriori dettagli. Non è una variabile di primo livello, poiché è collegata a un object, ma se si dispone di un ambito, qualsiasi cosa, è ansible allegarlo a tale object. this dovrebbe funzionare anche Quindi, per esempio, fare questo nello scope globale dichiarerà un valore di pseudo-costante sulla finestra (che è una pessima idea, non dovresti dichiarare incautamente le vars globali)

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

nota: l’assegnazione restituirà il valore assegnato nella console, ma il valore della variabile non cambierà

Raggruppare le costanti in strutture ove ansible:

Esempio, nel mio attuale progetto di gioco, ho usato di seguito:

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

Assegnazione:

 var wildType = CONST_WILD_TYPES.REGULAR; 

confronto:

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

Più recentemente sto usando, per il confronto:

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

IE11 è con il nuovo standard ES6 che ha la dichiarazione ‘const’.
Sopra funziona con browser precedenti come IE8, IE9 e IE10.

Puoi facilmente equipaggiare il tuo script con un meccanismo per le costanti che possono essere impostate ma non modificate. Un tentativo di alterarli genererà un errore.

 /* 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 

Dimentica IE e usa la parola chiave const .

Tuttavia non esiste un modo predefinito per il browser incrociato per farlo, puoi ottenerlo controllando l’ambito delle variabili come mostrato su altre risposte.

Ma suggerirò di usare lo spazio dei nomi per distinguere da altre variabili. questo ridurrà la possibilità di collisione al minimo da altre variabili.

Proprio come il namespacing

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

così mentre lo iw_constant.name sarà iw_constant.name o iw_constant.age

È inoltre ansible bloccare l’aggiunta di qualsiasi nuova chiave o la modifica di qualsiasi chiave all’interno di iw_constant utilizzando il metodo Object.freeze. Tuttavia non è supportato sul browser legacy.

ex:

 Object.freeze(iw_constant); 

Per i browser meno recenti è ansible utilizzare il polyfill per il metodo freeze.


Se stai bene con la funzione di chiamata seguente è il modo migliore per navigare tra i browser per definire la costante. Scoping dell’object all’interno di una funzione autoesposta e restituendo una funzione get per le costanti ex:

 var iw_constant= (function(){ var allConstant={ name:'sudhanshu', age:'23' //all varibale come like this }; return function(key){ allConstant[key]; } }; 

// per ottenere il valore usa iw_constant('name') o iw_constant('age')


** In entrambi gli esempi devi fare molta attenzione alla spaziatura dei nomi, in modo che il tuo object o la tua funzione non debbano essere sostituiti attraverso altre librerie. (Se l’object o la funzione stessa verranno sostituiti, l’intera costante andrà a finire)

Per un po ‘ho specificato “costanti” (che ancora non erano effettivamente costanti) nei letterali degli oggetti passati alle istruzioni with() . Pensavo fosse così intelligente. Ecco un esempio:

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

In passato, ho anche creato uno spazio dei nomi CONST cui avrei messo tutte le mie costanti. Di nuovo, con il sovraccarico. Sheesh.

Ora, faccio solo var MY_CONST = 'whatever'; BACIO .

La mia opinione (funziona solo con gli oggetti).

 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 

Provare! Ma capire – questo è object, ma non una variabile semplice.

Prova anche solo:

 const a = 9; 

Anch’io ho avuto un problema con questo. E dopo un po ‘di tempo cercando la risposta e osservando tutte le risposte di tutti, penso di aver trovato una soluzione praticabile a questo.

Sembra che la maggior parte delle risposte che ho incontrato stiano utilizzando le funzioni per mantenere le costanti. Come molti degli utenti dei forum di MANY pubblicano, le funzioni possono essere facilmente sovrascritte dagli utenti sul lato client. Sono stato affascinato dalla risposta di Keith Evetts che l’object costanti non è accessibile dall’esterno, ma solo dalle funzioni al suo interno.

Quindi ho trovato questa soluzione:

Metti tutto all’interno di una funzione anonima in questo modo, le variabili, gli oggetti, ecc. Non possono essere modificati dal lato client. Nascondi anche le funzioni “reali” facendo in modo che altre funzioni chiamino le funzioni “reali” dall’interno. Ho anche pensato di utilizzare le funzioni per verificare se una funzione è stata modificata da un utente sul lato client. Se le funzioni sono state modificate, cambiarle di nuovo usando le variabili che sono “protette” all’interno e non possono essere modificate.

 /*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); }; }()) 

Sembra anche che la sicurezza sia davvero un problema e non c’è modo di “hide” la programmazione dal lato client. Una buona idea per me è comprimere il tuo codice in modo che sia davvero difficile per chiunque, incluso te, il programmatore, leggerlo e capirlo. C’è un sito che puoi visitare: http://javascriptcompressor.com/ . (Questo non è il mio sito, non preoccuparti, non sto facendo pubblicità.) Questo è un sito che ti permetterà di comprimere e offuscare gratuitamente il codice Javascript.

  1. Copia tutto il codice nello script sopra e incollalo nella textarea superiore nella pagina javascriptcompressor.com.
  2. Controlla la casella di controllo Codifica Base62, seleziona la casella di controllo Riduci variabili.
  3. Premere il pulsante Comprimi.
  4. Incolla e salva tutto in un file .js e aggiungilo alla tua pagina nella parte superiore della pagina.

Chiaramente questo mostra la necessità di una parola chiave const standard per browser incrociati.

Ma per ora:

 var myconst = value; 

o

 Object['myconst'] = value; 

Entrambi sembrano sufficienti e qualsiasi altra cosa è come sparare una mosca con un bazooka.

Io uso const anziché var nei miei script di Greasemonkey, ma è perché funzioneranno solo su Firefox …
Anche la convention dei nomi può essere davvero la strada da percorrere (io faccio entrambe le cose!).

In JavaScript my practice has been to avoid constants as much as I can and use strings instead. Problems with constants appear when you want to expose your constants to the outside world:

For example one could implement the following Date API:

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

But it’s much shorter and more natural to simply write:

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

This way “days” and “hours” really act like constants, because you can’t change from the outside how many seconds “hours” represents. But it’s easy to overwrite MyModule.Date.HOUR .

This kind of approach will also aid in debugging. If Firebug tells you action === 18 it’s pretty hard to figure out what it means, but when you see action === "save" then it’s immediately clear.

Okay, this is ugly, but it gives me a constant in Firefox and Chromium, an inconstant constant (WTF?) in Safari and Opera, and a variable in IE.

Of course eval() is evil, but without it, IE throws an error, preventing scripts from running.

Safari and Opera support the const keyword, but you can change the const’s value .

In this example, server-side code is writing JavaScript to the page, replacing {0} with a value.

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

What is this good for? Not much, since it’s not cross-browser. At best, maybe a little peace of mind that at least some browsers won’t let bookmarklets or third-party script modify the value.

Tested with Firefox 2, 3, 3.6, 4, Iron 8, Chrome 10, 12, Opera 11, Safari 5, IE 6, 9.

If it is worth mentioning, you can define constants in angular using $provide.constant()

 angularApp.constant('YOUR_CONSTANT', 'value'); 

An improved version of Burke’s answer that lets you do CONFIG.MY_CONST instead of CONFIG.get('MY_CONST') .

It requires IE9+ or a real web browser.

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

* The properties are read-only, only if the initial values are immutable.

JavaScript ES6 (re-)introduced the const keyword which is supported in all major browsers .

Variables declared via const cannot be re-declared or re-assigned.

Apart from that, const behaves similar to let .

It behaves as expected for primitive datatypes (Boolean, Null, Undefined, Number, String, Symbol):

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

Attention: Be aware of the pitfalls regarding objects:

 const o = {x: 1}; o = {x: 2}; console.log(o); // {x: 1} ...as expected, re-assigning fails ox = 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 

If you really need an immutable and absolutely constant object: Just use const ALL_CAPS to make your intention clear. It is a good convention to follow for all const declarations anyway, so just rely on it.

Another alternative is something like:

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

Then simply: var foo = constantMap.MY_CONSTANT

If you were to constantMap.MY_CONSTANT = "bar" it would have no effect as we’re trying to use an assignment operator with a getter, hence constantMap.MY_CONSTANT === "myconstant" would remain true.

in Javascript already exists constants . You define a constant like this:

 const name1 = value; 

This cannot change through reassignment.

The keyword ‘const’ was proposed earlier and now it has been officially included in ES6. By using the const keyword, you can pass a value/string that will act as an immutable string.

Introducing constants into JavaScript is at best a hack.

A nice way of making persistent and globally accessible values in JavaScript would be declaring an object literal with some “read-only” properties like this:

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

you’ll have all your constants grouped in one single “my” accessory object where you can look for your stored values or anything else you may have decided to put there for that matter. Now let’s test if it works:

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

As we can see, the “my.constant1” property has preserved its original value. You’ve made yourself some nice ‘green’ temporary constants…

But of course this will only guard you from accidentally modifying, altering, nullifying, or emptying your property constant value with a direct access as in the given example.

Otherwise I still think that constants are for dummies. And I still think that exchanging your great freedom for a small corner of deceptive security is the worst trade possible.

Rhino.js implements const in addition to what was mentioned above.