Existem constantes em JavaScript?

1132

Existe uma maneira de usar constantes em JavaScript ?

Caso contrário, qual é a prática comum para especificar variáveis ​​usadas como constantes?

fuentesjr
fonte
35
Chromepermite que você use a palavra const- chave para usar constantes. por exemplo const ASDF = "asdf". No entanto, como constnão é compatível com vários navegadores, costumo ficar com uma vardeclaração.
Jacksonkr
20
try{const thing=1091;}catch(e){var thing=1091;}trabalho.
Derek朕會功夫
13
Derek: sua tentativa / captura não limitaria o escopo da coisa que você está declarando ao bloco tentativa / captura? Se você não está definindo o escopo corretamente, qual é o objetivo de especificar constou de vartodo?
Coderer
8
@Coderer nas implementações atuais, isso funcionará, pois consttem o mesmo escopo vare o nível de função, não o nível de bloco. Se você seguir o próximo padrão ECMAScript, terá consto mesmo escopo que let, o que significa que não funcionará.
Jasper
3
@Coderer Idioma errado. Variáveis ​​em javascript são escopo de função. Não é C.
doug65536 11/11

Respostas:

1018

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

const MY_CONSTANT = "some-value";

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

Você pode usar varcom 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";
John Millikin
fonte
60
Que tal const x = 24;
Zachary Scott
93
Observe que, se você não precisar de compatibilidade entre navegadores (ou estiver programando no Rhino ou Node.js.), poderá usar a constpalavra - chave. Atualmente, é suportado por todos os navegadores modernos, exceto o IE.
Husky
17
Hoje em dia (3,5 anos depois), você pode usar Object.definePropertypara criar propriedades somente leitura que também não podem ser excluídas. Isso funciona na versão atual de todos os principais navegadores (mas incorretamente no IE8 ). Veja a resposta por @NotAName
Phrogz
12
@ Amyy Isso não é realmente útil. É um guia de estilo proposto por um único fornecedor. Conforme o ponto de vista da Husky acima, a compatibilidade do IE é totalmente irrelevante ao escrever JS do lado do servidor.
aendrew
32
Como essa resposta ainda é altamente classificada pelo Google em 2015, deve-se dizer que agora está obsoleta. A constpalavra-chave agora faz parte oficialmente do idioma e é suportada por todos os navegadores. Segundo o statcounter.com, apenas alguns por cento dos usuários da Internet ainda usam versões antigas de navegadores que não eram compatíveis const.
tristan
310

Você está tentando proteger as variáveis ​​contra modificações? Nesse caso, 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ê precisa usar o método get () no CONFIG :(.

Se você não precisar proteger estritamente o valor das variáveis, faça o que é sugerido e use uma convenção de ALL CAPS.

Burke
fonte
13
Observe que você pode simplesmente retornar uma função para o valor de CONFIG. Isso economizaria você chamando CONFIG.get () o tempo todo.
Mathew Byrne
4
Bonita solução. Mas essas coisas devem ser agrupadas como uma biblioteca para não reinventá-las em nenhum novo projeto.
Andrii
82
CONFIG.get = someNewFunctionThatBreaksTheCode... Em suma, você absolutamente não pode impor constantes em JS (sem a palavra-chave const). A única coisa que você pode fazer é limitar a visibilidade.
Thomas Eding
28
Eu acredito que essa privateé uma palavra futura reservada em JavaScript, eu não usaria isso se fosse você.
Zaq 5/08/12
Esse também é o padrão do registro.
122

A constpalavra-chave está no rascunho do ECMAScript 6, mas até agora possui apenas um suporte considerável ao navegador: http://kangax.github.io/compat-table/es6/ . A sintaxe é:

const CONSTANT_NAME = 0;
Bill the Lizard
fonte
13
Se você tentar atribuir um valor a const, ele não gera erros. A atribuição simplesmente falha e a constante ainda tem seu valor original. Esta é uma das principais falhas de design do IMHO, mas enquanto houver uma convenção de nomenclatura clara e consistente (como o popular ALL_CAPS), não acho que isso causaria muita dor.
MatrixFrog
6
Fique de olho no suporte ao navegador aqui: kangax.github.io/es5-compat-table/es6/#const
Mark McDonald #
6
A atribuição @MatrixFrog irá gerar um erro com 'use strict'.
sam
Devo definir constantes em ALL CAPS?
Lewis
1
@ Tresdin É uma convenção de nomenclatura comum definir constantes em todas as maiúsculas. Nada na especificação do idioma o força, mas não é uma má idéia. Isso torna mais claro qual é a sua intenção e melhora a legibilidade do código.
Bill o Lagarto
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

Consulte Object.freeze . Você pode usarconst se quiser tornar a constantsreferência somente leitura.

sam
fonte
2
Deve mencionar que isso funciona apenas no IE9 + kangax.github.io/compat-table/es5 .
Cordle
Eu teria, se não tivesse a implementação interrompida dei
Alnitak 16/01
Nota: isso se comporta de maneira semelhante à constdeclaração ES6 , por exemplo, as propriedades não podem ser declaradas ou atribuídas novamente, mas, se forem do tipo de dados object, poderão ser alteradas.
21416 Le_m
Exatamente o que eu estava procurando. Você também pode usar em const constantsvez de var constantsimpedir que a variável seja reatribuída.
26517 Jarett Millard
Veja, por exemplo, congelamento profundo para congelamento recursivo.
7167 Sam
64

O IE suporta constantes, como, por exemplo:

<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
fonte
50
Rapaz, fale sobre algo que não é cross browser. . . Ainda +1 por pensar um pouco fora da caixa.
26269 Tom
14
VBScript? O que é isso? ;)
tybro0103
2
Normalmente voto para baixo para perguntas gerais relacionadas a vários navegadores, com uma resposta específica do IE. Porque eu odeio pessoas que pensam que a implementação de javascript do IE é 'The One', e outras devem ser ignoradas. Quem está usando outras ferramentas diferentes do IE, btw?
Ant
@Cooluhuru, este script parece manipular navegadores IE (usando VBScript) e navegadores não IE (usando JavaScript const). Você pode explicar o que há de errado com isso?
Andrew Grimm
Ainda tenho dificuldade em aceitar que as constantes possam ser alteradas.
Norbert Norbertson
59

O ECMAScript 5 apresenta Object.defineProperty:

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

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

Consulte também: Object.defineProperty no ES5?

Não é um nome
fonte
1
Vale a pena notar que isso não é como uma constante tradicional. Isso permitirá apenas definir uma propriedade constante (de um objeto não constante). Além disso, isso não gera um erro e até retorna o valor que você tenta definir. Simplesmente não escreve o valor.
Cory Gross
3
Recentemente, li que a tentativa de atribuir a uma propriedade realmente writable: false causará um erro se o código que executa a atribuição estiver sendo interpretado no modo estrito do ECMAScript 5. Apenas outro motivo para escrever 'use strict'no seu código.
Cory Gross
6
Você pode realmente omitir, writable: falsejá que esse é o padrão .
sam
24

Não, não em geral. O Firefox implementa, constmas eu sei que o IE não.


@John aponta para uma prática comum de nomeação para consts que é usada há anos em outros idiomas. Não vejo razão para que você não possa usá-la. Claro que isso não significa que alguém não irá escrever sobre o valor da variável de qualquer maneira. :)

Jason Bunting
fonte
11
Como todos sabem, se o IE não implementá-lo, ele também pode não existir.
Josh Hinman
3
Infelizmente, e praticamente falando - é verdade. O IE possui uma grande fatia do mercado. Se eu fosse dono de uma empresa e tivesse aplicativos da Web usados ​​internamente, padronizaria no FF. Eu não sei por que tantas pessoas se importam com o IE, isso explode.
Jason Bunting
@ Rich: Quem disse que minha opinião era verdade? Você fez bastante suposição. Além disso, para mim, o fato de o IE ser péssimo é um fato. Você pode ter seus próprios fatos, eu não disse que você tinha que acreditar nos meus. : P Pegue um Xanax ou algo assim ...
Jason Bunting
@ Rich B, sim, isso foi apenas um comentário idiota para fazer, e confie em mim, eu saberia, faço muitos comentários idiotas. @ Jason B. - interessante, eu me deparei com esse mesmo problema ontem à noite .. const trabalhou em FF, mas não no IE. Obrigado por esclarecer
Quem se importa com o IE? Eu não! FF ou Chrome ou Opera etc ... podem ser instalados quase em todas as plataformas de SO. Além disso, os varejistas de computadores geralmente sabem que a versão antiga do IE é uma porcaria, então eles frequentemente (ou mesmo toda vez) instalam navegadores alternativos antes de vender um computador. Então, decidi que meu aplicativo desenvolvido não se importaria com navegadores incompatíveis: se os desenvolvedores de navegadores se importam em respeitar os padrões, o produto pode usar meu aplicativo; caso contrário, os usuários usarão um navegador diferente ... Eu posso conviver com ele; -) Mas a Microsoft pode viver perdendo parte do mercado? Não, eles não podem, então "Eles" mudarão seu desenvolvimento político!
Willy wonka
20

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

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


alert(MY_CONSTANT());
MTS
fonte
6
Vale ressaltar que isso se enquadra no mesmo problema mencionado na resposta do @Burkes (comentário do @trinithis '). `MY_CONSTANT = function () {retorna" algum outro valor "; } quebra. +1, porém, solução decente e rápida.
317 Patrick M
13
-1. Isso não tem benefício sobre var SOME_NAME = value (ainda é mutável), é mais código e requer explicação.
Mikemaccana #
@PatrickM, embora seja verdade que você pode modificar esse tipo de pseudo-constantes, em outros idiomas como, por exemplo, C, nos quais você não pode modificar constantes, você ainda pode fazê-lo através de, por exemplo, ponteiros. Então, desde que você use alguma abordagem que pelo menos sugira que seja uma constante, tudo bem.
rev
20

Os Documentos da Web MDN da Mozillas 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 aguardar os processos de padronização seguirem seu curso.

Eles não o implementam porque outros navegadores não o implementaram corretamente ?! Com muito medo de melhorar? Definições de padrões ou não, uma constante é uma constante: defina uma vez, nunca mude.

E para todas as idéias: Todas as funções podem ser substituídas (XSS etc.). Portanto, não há diferença em varou function(){return}. consté a única constante real.

Atualização: O IE11 suporta const :

IE11 inclui suporte para as características bem definidas e vulgarmente utilizadas do padrão ECMAScript 6 emergente incluindo let, const, Map, Set, e WeakMap, bem como __proto__para melhorar a interoperabilidade.

mgutt
fonte
25
"nunca esteve disponível em todos os navegadores". Se você não disponibilizá-lo no IE, ele nunca estará em todos os navegadores.
precisa
padronização de condução não é para todos;) - empresas vêm e vão novamente - obrigado por citar as probabilidades na madeira
Mais rápido
mais sobre este um: VBA não é uma característica consesus em todos os navegadores e ainda MS suportes const no VBA - este é o domínio de canalizar os orçamentos de desenvolvimento;)
Mais rápido
17

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 variáveis ​​regulares, mas garante * que ninguém poderá 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 de observáveis ​​nocauteados.

* A menos que alguém redefina a função constantantes de chamá-la

hasen
fonte
1
O underscore.js implementa uma função constante idêntica a esse código.
Upperstage
Simples, conciso e responde ao espírito da pergunta do OP. Isso deveria ter recebido mais upVotes.
Mac
3
Isso nunca realmente funcionou para mim. Mesmo que o fechamento o torne imutável, o var ao qual você o atribui ainda pode ser substituído. Ex: a = constant(10); a(10); // 10seguido por a = constant(25); a(); //25, sem erros ou avisos, sem indicação de que sua constante foi quebrada.
Patrick M
Se eu valor Reassign para aentão é alterações ao novo valor
Saurabh Sharma
17

com a "API" nova Object, 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 obter mais detalhes. Não é uma variável de primeiro nível, pois está anexada a um objeto, mas se você tiver um escopo, qualquer coisa, poderá anexá-lo a isso. thisdeve funcionar também. Assim, por exemplo, fazer isso no escopo global declarará um valor pseudo-constante na janela (o que é uma péssima idéia, você não deve declarar vars globais descuidadamente)

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

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

nota: a atribuição retornará o valor atribuído no console, mas o valor da variável não será alterado

tenshou
fonte
Não funcionando no safari, e no mozilla, se você executar a instrução define novamente - com um valor diferente - ele irá reatribuir o valor.
Akshay
2
Não 'não está trabalhando no safari', não é suportado no safari. Não é o mesmo. E ele deve gerar um 'UnAught TypeError: Não é possível redefinir a propriedade: <nome da propriedade aqui>' se você tentar isso. ou você está fazendo errado ou seu ff o implementou incorretamente. Eu acho que é uma mistura de ambos.
tenshou
14

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

O IE11 está com o novo padrão ES6 que possui declaração 'const'.
Acima funciona em navegadores anteriores como IE8, IE9 e IE10.

Manohar Reddy Poreddy
fonte
12

Você pode equipar seu script facilmente 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  
Keith
fonte
12

Esqueça o IE e use a constpalavra - chave.

Derek 朕 會 功夫
fonte
9
funciona para mim! mas então eu estou escrevendo uma extensão do Chrome, então eu sei que estou em um navegador sã ...
yoyo
1
A melhor parte do @yoyo sobre como escrever extensões e complementos - sem suporte para vários navegadores!
Ian Ian
1
Bem-vindo @Ian a 2019, a inconsistência cross-browser quase desapareceu :)
Fusseldieb
9

No entanto, não existe uma maneira predefinida exata para fazer isso entre navegadores; você pode alcançá-lo controlando o escopo das variáveis, como mostrado em outras respostas.

Mas vou sugerir o uso de espaço para nome para distinguir de outras variáveis. isso reduzirá a chance de colisão ao mínimo de outras variáveis.

Espaço de nome apropriado como

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

então enquanto estiver usando será iw_constant.nameouiw_constant.age

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

ex:

Object.freeze(iw_constant);

Para navegadores mais antigos, você pode usar o método polyfill for freeze.


Se você estiver de acordo com a função de chamada a seguir, é melhor definir o modo entre navegadores para definir constante. Escopo seu objeto dentro de uma função auto-executável e retorno de uma função 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')ouiw_constant('age')


** Nos dois exemplos, você deve ter muito cuidado com o espaçamento de nomes, para que seu objeto ou função não seja substituído por outra biblioteca (se o objeto ou função em si for substituído, toda a sua constante desaparecerá)

Sudhanshu Yadav
fonte
7

Por um tempo, especifiquei "constantes" (que na verdade ainda não eram constantes) em literais de objetos passados ​​para with()instruções. 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 CONSTespaço para nome onde colocaria todas as minhas constantes. Mais uma vez, com a sobrecarga. Sheesh.

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

Andrew Hedges
fonte
16
Se há algo mais mal do que eval, é definitivamente with.
NikiC
4
eval é muito mau! Queimou minha casa uma vez!
W3Geek
6

Minha opinião (funciona apenas com objetos).

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

Tentar! Mas entenda - este é um objeto, mas não uma variável simples.

Tente também apenas:

const a = 9;
user1635543
fonte
5

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

Parece que a maioria das respostas que encontrei está usando funções para manter as constantes. Como muitos usuários dos MUITOS fóruns publicam, as funções podem ser facilmente substituídas por usuários no lado do cliente. Fiquei intrigado com a resposta de Keith Evetts de que o objeto de constantes não pode ser acessado por fora, mas apenas pelas funções internas.

Então, eu vim com esta solução:

Coloque tudo dentro de uma função anônima para que as variáveis, objetos etc. não possam ser alterados pelo lado do cliente. Oculte também as funções 'reais' fazendo com que outras funções chamem as funções 'reais' por dentro. Também pensei em usar funções para verificar se uma função foi alterada por um usuário no lado do cliente. Se as funções foram alteradas, altere-as novamente usando variáveis ​​que são 'protegidas' por dentro 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á como 'ocultar' sua programação do lado do cliente. Uma boa idéia para mim é compactar seu código para que seja realmente difícil para qualquer pessoa, incluindo você, o programador, ler e entender. Existe um site que você pode acessar: http://javascriptcompressor.com/ . (Este não é o meu site, não se preocupe, não estou anunciando.) Este é um site que permitirá compactar e ofuscar o código Javascript gratuitamente.

  1. Copie todo o código no script acima e cole-o na área de texto superior na página javascriptcompressor.com.
  2. Marque a caixa de seleção Codificar Base62, marque a caixa de seleção Encolher variáveis.
  3. Pressione o botão Compactar.
  4. Cole e salve tudo isso em um arquivo .js e adicione-o à sua página no cabeçalho da sua página.
Steven Kapaun
fonte
Esta é uma boa solução que pode ser agrupada como uma biblioteca para incluir. Mas eu não gosto do nome de suas variáveis ​​neste código. Por que largar os nomes descritivos como "nome" e "valor", conforme usados ​​no código de Keith? Problema menor, mas ainda assim.
Cordle
5

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 uma mosca com uma bazuca.

codemuncher
fonte
pegue o bom e velho var myconst = value; e para depurar o uso extra de depuração de código ... - funciona como um louco enquanto nem todos os navegadores suportam const
Mais rápido
4

Eu uso em constvez dos varmeus scripts Greasemonkey, mas é porque eles serão executados apenas no Firefox ... A
convenção de nomes também pode ser o caminho a percorrer (eu faço os dois!).

PhiLho
fonte
4

Em JavaScript, minha prática é evitar constantes o máximo possível e usar cadeias de caracteres. Problemas com constantes aparecem quando você deseja expor suas constantes para o mundo exterior:

Por exemplo, pode-se implementar a seguinte API de data:

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

Mas é muito mais curto e mais natural simplesmente escrever:

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

Dessa forma, "dias" e "horas" realmente agem como constantes, porque você não pode mudar externamente quantos segundos "horas" representa. Mas é fácil substituir MyModule.Date.HOUR.

Esse tipo de abordagem também ajudará na depuração. Se o Firebug diz action === 18que é muito difícil descobrir o que isso significa, mas quando você vê action === "save", fica imediatamente claro.

Rene Saarsoo
fonte
Infelizmente, é muito fácil cometer erros de ortografia - por exemplo, em "Hours"vez de "hours"- mas um IDE pode informar você desde o início que Date.Hoursnão está definido.
le_m
4

Ok, isso é feio, mas me dá uma constante no Firefox e no Chromium, uma constante inconstante (WTF?) No Safari e Opera e uma variável no IE.

É claro que eval () é ruim, mas sem ele, o IE gera um erro, impedindo a execução de scripts.

O Safari e o Opera suportam a palavra-chave const, mas você pode alterar o valor da const .

Neste exemplo, o código do lado do servidor está gravando JavaScript na página, substituindo {0} por um valor.

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

Para que serve isso? Não muito, já que não é entre navegadores. Na melhor das hipóteses, talvez tenha um pouco de tranqüilidade de que pelo menos alguns navegadores não permitam que bookmarklets ou scripts de terceiros modifiquem o valor.

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

Webveloper
fonte
1
Ame esse código! Feio como o diabo, mas um bom teste para o apoio constante. =)
Stein G. Strindhaug
1
um pouco engraçado, ey - quantas linhas você pode digitar para declarar uma const?
Mais rápido
4

Se vale a pena mencionar, você pode definir constantes em angular usando$provide.constant()

angularApp.constant('YOUR_CONSTANT', 'value');
Muhammad Reda
fonte
... e você pode usar const no VBA ... xbrowser? ... ups ...;)
rápido
O OP pergunta sobre javascript, a resposta lida com uma estrutura JS altamente opinativa específica. Praticamente fora de tópico.
rounce
2
@rounce: respostas off-topic ainda respostas, não flag -los como não é uma resposta , mas downvote e voto para excluir vez. Consulte Como uso corretamente o sinalizador "Não é uma resposta"?
Kevin Guan
@ KevinGuan Noted, fará no futuro.
rounce
4

Uma versão aprimorada da resposta de Burke que permite que você faça em CONFIG.MY_CONSTvez de CONFIG.get('MY_CONST').

Requer o IE9 + ou um navegador da web real.

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

* As propriedades são somente leitura, apenas se os valores iniciais forem imutáveis.

Şafak Gür
fonte
4

O JavaScript ES6 (re) introduziu a constpalavra - chave suportada em todos os principais navegadores .

Variáveis ​​declaradas via constnão podem ser declaradas ou atribuídas novamente.

Além disso, constcomporta-se de maneira semelhante let.

Ele se comporta conforme o esperado para tipos de dados primitivos (Boolean, Null, Undefined, Number, String, Symbol):

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

Atenção: Esteja ciente das armadilhas relacionadas aos objetos:

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

Se você realmente precisa de um objeto imutável e absolutamente constante: use const ALL_CAPSpara deixar sua intenção clara. É uma boa convenção seguir todas as constdeclarações de qualquer maneira, portanto, basta confiar nela.

le_m
fonte
De IE11 única :-(
Mo.
3

Outra alternativa é algo como:

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

Então simplesmente: var foo = constantMap.MY_CONSTANT

Se você constantMap.MY_CONSTANT = "bar"aceitasse, isso não teria efeito, pois estamos tentando usar um operador de atribuição com um getter, portanto constantMap.MY_CONSTANT === "myconstant", permaneceria verdadeiro.

atacar
fonte
3

em Javascript já existe constantes . Você define uma constante como esta:

const name1 = value;

Isso não pode mudar através da reatribuição.

Erik Lucio
fonte
Pelo link da resposta, esse é um recurso experimental e deve ser usado com cautela.
precisa
Claro, eu concordo com você. Mas nas últimas versões de navegadores Funciona.
Erik Lucio
3

A palavra-chave 'const' foi proposta anteriormente e agora foi oficialmente incluída no ES6. Usando a palavra-chave const, você pode transmitir um valor / string que atuará como uma string imutável.

Ritumoni Sharma
fonte
2

A introdução de constantes no JavaScript é, na melhor das hipóteses, um hack.

Uma boa maneira de tornar valores persistentes e acessíveis globalmente em JavaScript seria declarar um objeto literal com algumas propriedades "somente leitura" como esta:

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

você terá todas as suas constantes agrupadas em um único objeto acessório "meu", onde poderá procurar seus valores armazenados ou qualquer outra coisa que você tenha decidido colocar lá para esse assunto. Agora vamos testar se funciona:

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

Como podemos ver, a propriedade "my.constant1" preservou seu valor original. Você fez algumas constantes temporárias 'verdes' agradáveis ​​...

Mas é claro que isso apenas o impedirá de modificar, alterar, anular ou esvaziar acidentalmente o valor constante da sua propriedade com acesso direto, como no exemplo fornecido.

Caso contrário, ainda acho que as constantes são para manequins. E ainda acho que trocar sua grande liberdade por uma pequena parte da segurança enganosa é a pior negociação possível.

Bill the Lizard
fonte
2

Rhino.jsimplementa constalém do mencionado acima.

isomorfismos
fonte