Existem constantes em JavaScript?

Existe uma maneira de usar constantes em JavaScript?

Se não, qual é a prática comum para especificar variables ​​que são usadas como constantes?

   

Desde ES2015 , JavaScript tem uma noção de const :

 const MY_CONSTANT = "some-value"; 

Isso funcionará em praticamente todos os navegadores, exceto o IE 8, 9 e 10 . Alguns também podem precisar do modo estrito ativado.

Você pode usar var com convenções como ALL_CAPS para mostrar que determinados valores não devem ser modificados se você precisar oferecer suporte a navegadores mais antigos ou se estiver trabalhando com código legado:

 var MY_CONSTANT = "some-value"; 

Você está tentando proteger as variables ​​contra modificação? Em caso afirmativo, você pode usar um padrão de módulo:

 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 

Usando essa abordagem, os valores não podem ser modificados. Mas, você tem que usar o método get () em CONFIG :(.

Se você não precisa proteger rigorosamente o valor das variables, faça como sugerido e use uma convenção de ALL CAPS.

A palavra-chave const está no rascunho do ECMAScript 6, mas até o momento apenas desfruta de um pouco de suporte ao navegador: http://kangax.github.io/compat-table/es6/ . A 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 

Veja Object.freeze . Você pode usar const se quiser fazer as constants referenciar somente leitura também.

O IE suporta constantes, por exemplo:

   

O ECMAScript 5 introduz o Object.defineProperty :

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

É suportado em todos os navegadores modernos (assim como no IE ≥ 9).

Veja também: Object.defineProperty no ES5?

Não, não em geral. O Firefox implementa const mas sei que o IE não.


@John aponta para uma prática de nomenclatura comum para consts que tem sido usada há anos em outros idiomas, não vejo razão para você não poder usá-la. Claro que isso não significa que alguém não vai escrever sobre o valor da variável de qualquer maneira. 🙂

Docs Web do Mozillas MDN contêm bons exemplos e explicações sobre const . Excerto:

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

Mas é triste que o IE9 / 10 ainda não suporte const . E a razão é absurda :

Então, o que o IE9 está fazendo com const? Até agora, nossa decisão foi não apoiá-lo. Ainda não é um recurso de consenso, pois nunca esteve disponível em todos os navegadores.

No final, parece que a melhor solução a longo prazo para a Web é deixá-la de fora e esperar que os processos de padronização sigam o seu curso.

Eles não o implementam porque outros navegadores não o implementaram corretamente ?! Demasiado medo de fazer melhor? Definições de padrões ou não, uma constante é uma constante: set once, never changed.

E para todas as ideias: todas as funções podem ser sobrescritas (XSS etc.). Portanto, não há diferença em var ou function(){return} . const é a única constante real.

Atualização: IE11 suporta const :

O IE11 inclui suporte para os resources bem definidos e comumente usados ​​do padrão emergente ECMAScript 6 incluindo let, const , Map , Set e WeakMap , bem como __proto__ para melhor interoperabilidade.

Em JavaScript, minha preferência é usar funções para retornar valores constantes.

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

Se você não se importa em usar funções:

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

Essa abordagem fornece funções em vez de variables ​​regulares, mas garante * que ninguém pode alterar o valor depois de definido.

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

Pessoalmente, acho isso bastante agradável, especialmente depois de me acostumar com esse padrão dos observáveis ​​nocautes.

* A menos que alguém tenha redefinido a function constant antes de chamá-la

com o “novo” Object API você pode fazer algo assim:

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

Dê uma olhada nisso no Mozilla MDN para mais detalhes. Não é uma variável de primeiro nível, pois é anexada a um object, mas se você tem um escopo, qualquer coisa, você pode anexá-lo a isso. this deve funcionar também. Então, por exemplo, fazer isso no escopo global irá declarar um valor pseudo-constante na janela (o que é uma idéia muito ruim, você não deve declarar descuidado globalmente)

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

nota: atribuição lhe dará de volta o valor atribuído no console, mas o valor da variável não será alterado

Agrupar constantes em estruturas sempre que possível:

Exemplo, no meu projeto de jogo atual, usei abaixo:

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

Tarefa:

 var wildType = CONST_WILD_TYPES.REGULAR; 

Comparação:

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

Mais recentemente estou usando, para comparação:

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

IE11 é com novo padrão ES6 que tem declaração ‘const’.
Acima funciona em navegadores anteriores como IE8, IE9 e IE10.

Você pode facilmente equipar seu script com um mecanismo para constantes que podem ser definidas, mas não alteradas. Uma tentativa de alterá-los gerará um erro.

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

Esqueça o IE e use a palavra-chave const .

No entanto, não existe uma maneira predefinida de fazer o cross browser, você pode consegui-lo controlando o escopo das variables, como mostrado em outras respostas.

Mas vou sugerir usar espaço de nome para distinguir de outras variables. isso reduzirá a chance de colisão para o mínimo de outras variables.

Namespacing adequado como

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

então, enquanto estiver usando, será iw_constant.name ou iw_constant.age

Você também pode bloquear a adição de qualquer nova chave ou alterar qualquer chave dentro do iw_constant usando o método Object.freeze. No entanto, não é suportado no navegador legado.

ex:

 Object.freeze(iw_constant); 

Para o navegador mais antigo, você pode usar o polyfill para o método de congelamento.


Se você está ok com a function de chamada seguinte é melhor maneira cross-browser para definir constante. Scoping seu object dentro de uma function auto-executável e retornando uma function get para suas constantes ex:

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

// para obter o valor use iw_constant('name') ou iw_constant('age')


** Em ambos os exemplos, você deve ter muito cuidado com o espaçamento de nomes, para que seu object ou function não seja substituído por outra biblioteca (se o object ou function em si for substituído, toda a sua constante irá)

Por um tempo, eu especifiquei “constantes” (que ainda não eram realmente constantes) em literais de objects passados ​​através de declarações with() . Eu pensei que era tão inteligente. Aqui está um exemplo:

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

No passado, eu também criei um namespace CONST onde eu colocaria todas as minhas constantes. Mais uma vez, com a sobrecarga. Sheesh

Agora, eu apenas faço var MY_CONST = 'whatever'; para beijar .

Minha opinião (funciona apenas com objects).

 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 

Experimentar! Mas entenda – isso é object, mas não variável simples.

Experimente também apenas:

 const a = 9; 

Eu também tive um problema com isso. E depois de um bom tempo procurando a resposta e olhando todas as respostas de todos, acho que encontrei uma solução viável para isso.

Parece que a maioria das respostas que eu encontrei está usando funções para manter as constantes. Como muitos dos usuários do MANY postam sobre, as funções podem ser facilmente escritas pelos usuários no lado do cliente. Fiquei intrigado com a resposta de Keith Evetts de que o object das constantes não pode ser acessado pelo lado de fora, mas apenas pelas funções internas.

Então eu criei esta solução:

Coloque tudo dentro de uma function anônima para que as variables, objects, etc. não possam ser alterados pelo lado do cliente. Também esconda as funções ‘reais’ fazendo outras funções chamarem as funções ‘reais’ de dentro. Eu também pensei em usar funções para verificar se uma function foi alterada por um usuário no lado do cliente. Se as funções foram alteradas, altere-as de volta usando variables ​​que estão “protegidas” no interior e não podem ser alteradas.

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

Parece também que a segurança é realmente um problema e não há maneira de “ocultar” sua programação do lado do cliente. Uma boa ideia para mim é compactar seu código para que seja realmente difícil para qualquer um, inclusive você, o programador, ler e entender. Existe um site para o qual você pode ir: http://javascriptcompressor.com/ . (Este não é o meu site, não se preocupe, eu não estou anunciando.) Este é um site que permite comprimir e ofuscar o código JavaScript gratuitamente.

  1. Copie todo o código no script acima e cole-o na textarea superior na página javascriptcompressor.com.
  2. Marque a checkbox de seleção de codificação Base62, marque a checkbox de seleção Shrink Variables.
  3. Pressione o botão Compactar.
  4. Cole e salve tudo em um arquivo .js e adicione-o à sua página na cabeça da sua página.

Claramente, isso mostra a necessidade de uma palavra-chave const padronizada entre navegadores.

Mas para agora:

 var myconst = value; 

ou

 Object['myconst'] = value; 

Ambos parecem suficientes e qualquer outra coisa é como atirar numa mosca com uma bazuca.

Eu uso const vez de var em meus scripts do Greasemonkey, mas é porque eles rodam apenas no Firefox …
A convenção de nomes também pode ser o caminho a percorrer (eu faço as duas coisas!).

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.