¿Hay constantes en JavaScript?

1132

¿Hay alguna manera de usar constantes en JavaScript ?

Si no, ¿cuál es la práctica común para especificar variables que se usan como constantes?

fuentesjr
fuente
35
Chromele permite usar la palabra clave constpara usar constantes. por ej const ASDF = "asdf". Sin embargo, dado constque no es compatible con varios navegadores, generalmente me quedo con una vardeclaración.
Jacksonkr
20
try{const thing=1091;}catch(e){var thing=1091;}trabajos.
Derek 朕 會 功夫
13
Derek: ¿tu try / catch no limitaría el alcance de lo que estás declarando al bloque try / catch? Si no está explorando correctamente, ¿cuál es el punto de especificar consto varen absoluto?
Coderer
8
@Coderer en las implementaciones actuales, esto funcionará, ya que consttiene el mismo alcance que var, y eso es a nivel de función, no a nivel de bloque. Si sigue el próximo estándar ECMAScript, consttiene el mismo alcance que let, lo que significa que no funcionará.
Jasper
3
@Coderer Lenguaje incorrecto. Las variables en javascript son el alcance de la función. Esto no es C.
doug65536

Respuestas:

1018

Desde ES2015 , JavaScript tiene una noción de const:

const MY_CONSTANT = "some-value";

Esto funcionará en casi todos los navegadores, excepto IE 8, 9 y 10 . Algunos también pueden necesitar el modo estricto habilitado.

Puede usar varconvenciones como ALL_CAPS para mostrar que ciertos valores no deben modificarse si necesita admitir navegadores más antiguos o si está trabajando con código heredado:

var MY_CONSTANT = "some-value";
John Millikin
fuente
6060
¿Qué tal const x = 24;
Zachary Scott
93
Tenga en cuenta que si no necesita compatibilidad entre navegadores (o si está programando del lado del servidor en Rhino o Node.js) puede usar la constpalabra clave. Actualmente es compatible con todos los navegadores modernos, excepto IE.
Husky
17
En estos días (3,5 años después) puede usar Object.definePropertypara crear propiedades de solo lectura que tampoco se pueden eliminar. Esto funciona en la versión actual de todos los principales navegadores (pero incorrectamente en IE8 ). Ver la respuesta de @NotAName
Phrogz
12
@Amyth Eso no es realmente útil. Es una guía de estilo propuesta por un único vendedor. Según el punto anterior de Husky, la compatibilidad con IE es totalmente irrelevante al escribir JS del lado del servidor.
aendrew el
32
Dado que esta respuesta aún está altamente clasificada por Google en 2015, se debe decir que ahora está obsoleta. La constpalabra clave ahora es oficialmente parte del idioma y es compatible con todos los navegadores. De acuerdo con statcounter.com, solo un pequeño porcentaje de usuarios de Internet todavía usa versiones antiguas del navegador que no son compatibles const.
tristan
310

¿Estás tratando de proteger las variables contra modificaciones? Si es así, puede usar un patrón 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

Con este enfoque, los valores no pueden modificarse. Pero, debe usar el método get () en CONFIG :(.

Si no necesita proteger estrictamente el valor de las variables, simplemente haga lo sugerido y use una convención de ALL CAPS.

Burke
fuente
13
Tenga en cuenta que podría devolver una función para el valor de CONFIG. Eso te ahorraría llamar a CONFIG.get () todo el tiempo.
Mathew Byrne
44
Bonita solución. Pero esas cosas deben envolverse como una biblioteca para no reinventarlas en ningún proyecto nuevo.
andrii
82
CONFIG.get = someNewFunctionThatBreaksTheCode... En general, absolutamente no puede aplicar constantes en JS (sin palabra clave const). Casi lo único que puede hacer es limitar la visibilidad.
Thomas Eding
28
Creo que privatees una palabra reservada para el futuro en JavaScript, no la usaría si fuera usted.
Zaq
Este es también el patrón de registro.
122

La constpalabra clave se encuentra en el borrador de ECMAScript 6, pero hasta ahora solo cuenta con una pequeña cantidad de compatibilidad con el navegador: http://kangax.github.io/compat-table/es6/ . La sintaxis es:

const CONSTANT_NAME = 0;
Bill el lagarto
fuente
13
Si intenta asignar un valor a a const, no arroja ningún error. La asignación simplemente falla y la constante todavía tiene su valor original. Este es un defecto de diseño importante en mi humilde opinión, pero siempre que haya una convención de nomenclatura clara y coherente (como la popular ALL_CAPS), no creo que cause demasiado dolor.
MatrixFrog
66
Esté
Mark McDonald
66
La asignación de @MatrixFrog generará un error con 'use strict'.
Sam
¿Debo definir constantes en ALL CAPS?
Lewis
1
@Tresdin Es una convención de nomenclatura común definir constantes en mayúsculas. Nada en la especificación del idioma lo obliga, pero no es una mala idea. Aclara cuál es su intención, por lo que mejora la legibilidad del código.
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

Ver Object.freeze . Puede usarloconst si desea que la constantsreferencia también sea de solo lectura.

sam
fuente
2
Debería mencionar que esto solo funciona en IE9 + kangax.github.io/compat-table/es5 .
Cordle
Me gustaría, si no tenía la aplicación de rotoi
Alnitak
Nota: esto se comporta de manera similar a la constdeclaración ES6 , por ejemplo, las propiedades no se pueden volver a declarar o reasignar, pero si son de tipo de datos object, se pueden mutar.
le_m
Exactamente lo que estaba buscando. También puede usar en const constantslugar de var constantsevitar que la variable se reasigne.
Jarett Millard
Ver, por ejemplo, congelación profunda para congelación recursiva.
sam
64

IE admite constantes, más o menos, por ejemplo:

<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
fuente
50
Chico, habla sobre algo que no sea un navegador cruzado. . . Todavía +1 por pensar un poco fuera de la caja.
Tom
14
VBScript? ¿Que es eso? ;)
tybro0103
2
Por lo general, voto hacia abajo para preguntas generales relacionadas con navegadores cruzados, con una respuesta específica de IE. Porque odio a las personas que piensan que la implementación de IE javascript es 'la única', y otras solo deben ser ignoradas. ¿Quién está usando otras personas que no sean IE, por cierto?
Ant
@Cooluhuru, este script parece manejar tanto los navegadores IE (usando VBScript) como los navegadores que no son IE (usando JavaScript const). ¿Puedes explicar qué le pasa?
Andrew Grimm
Todavía me cuesta aceptar que las constantes se pueden cambiar.
Norbert Norbertson
59

ECMAScript 5 introduce Object.defineProperty:

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

Es compatible con todos los navegadores modernos (así como IE ≥ 9).

Ver también: Object.defineProperty en ES5?

No es un nombre
fuente
1
Vale la pena señalar que esto no es como una constante tradicional. Esto solo le permitirá definir una propiedad constante (de un objeto no constante). Además, esto no genera un error e incluso devuelve el valor que intenta establecer. Simplemente no escribe el valor.
Cory Gross
3
Hace poco leí que el intento de asignar a una propiedad con writable: false será en realidad un error si el código que hace la tarea está siendo interpretado en modo estricto de ECMAScript 5. Solo otra razón para escribir 'use strict'en su código.
Cory Gross
66
En realidad, puede omitir writable: falseya que ese es el valor predeterminado .
sam
24

No, no en general. Firefox implementa constpero sé que IE no.


@John señala una práctica de nomenclatura común para concursos que se ha utilizado durante años en otros idiomas, no veo ninguna razón por la que no pueda usar eso. Por supuesto, eso no significa que alguien no escribirá sobre el valor de la variable de todos modos. :)

Jason Bunting
fuente
11
Como todos saben, si IE no lo implementa, bien podría no existir.
Josh Hinman
3
Desafortunadamente, y prácticamente hablando, es cierto. IE posee una gran parte del mercado. Si fuera dueño de un negocio y tuviera aplicaciones web utilizadas internamente, estandarizaría en FF. No sé por qué tanta gente se preocupa por IE, explota.
Jason Bunting
@Rich: ¿Quién dijo que mi opinión era un hecho? Hiciste toda la suposición. Además, en lo que a mí respecta, el hecho de que IE apesta es un hecho. Puedes tener tus propios hechos, no dije que debías creer los míos. : P Toma un Xanax o algo así ...
Jason Bunting
@ Rich B, sí, eso fue solo un comentario tonto para hacer, y confía en mí, lo sabría, hago muchos comentarios tontos. @Jason B. - interesante, me encontré con este mismo problema anoche ... const funcionó en FF pero no en IE. Gracias por la aclaración
¿A quién le importa IE? ¡Yo no! FF o Chrome u Opera, etc ... se pueden instalar en casi todas las plataformas de SO Además, los minoristas de computadoras generalmente saben que la versión anterior de IE es una mierda, por lo que a menudo (o incluso cada vez) instalan navegadores alternativos antes de vender una computadora. Así que he decidido que mi aplicación desarrollada no se preocupe en absoluto por los navegadores incompatibles: si los desarrolladores de navegadores se preocupan por respetar los estándares, su producto puede usar mi aplicación, de lo contrario, los usuarios usarán un navegador diferente ... Puedo vivir con ella; -) ¿Pero puede Microsoft vivir perdiendo parte del mercado? ¡No, no pueden, así que "ellos" cambiarán su política de desarrollo!
willy wonka
20

En JavaScript, mi preferencia es usar funciones para devolver valores constantes.

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


alert(MY_CONSTANT());
MTS
fuente
66
Vale la pena señalar que esto cae en el mismo problema mencionado en la respuesta de @Burkes (comentario de @trinithis). `MY_CONSTANT = function () {return" algún otro valor "; } lo rompe. +1 sin embargo, solución decente y rápida.
Patrick M
13
-1. Esto no tiene ningún beneficio sobre var SOME_NAME = value (todavía es mutable), es más código y requiere explicación.
mikemaccana
@PatrickM, si bien es cierto que puede modificar ese tipo de pseudoconstantes, en otros lenguajes como, por ejemplo, C, en el que no debería poder modificar constantes, aún puede hacerlo a través de, por ejemplo, punteros. Entonces, siempre y cuando use algún enfoque que al menos sugiera que es una constante, está bien.
rev
20

Los documentos web de Mozillas MDN contienen buenos ejemplos y explicaciones sobre const. Extracto:

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

Pero es triste que IE9 / 10 todavía no sea compatible const. Y la razón es absurda :

Entonces, ¿qué está haciendo IE9 con const? Hasta ahora, nuestra decisión ha sido no apoyarlo. Todavía no es una función de consenso, ya que nunca ha estado disponible en todos los navegadores.

...

Al final, parece que la mejor solución a largo plazo para la web es dejarla de lado y esperar a que los procesos de estandarización sigan su curso.

¿No lo implementan porque otros navegadores no lo implementaron correctamente? ¿Demasiado miedo de hacerlo mejor? Definiciones de estándares o no, una constante es una constante: establece una vez, nunca cambia.

Y a todas las ideas: cada función se puede sobrescribir (XSS, etc.). Entonces no hay diferencia en varo function(){return}. constEs la única constante real.

Actualización: IE11 admite const :

EI11 incluye soporte para las características bien definidas y de uso general de la norma ECMAScript 6 emergentes incluyendo let, const, Map, Set, y WeakMap, así como __proto__para la interoperabilidad mejorada.

mgutt
fuente
25
"nunca ha estado disponible en todos los navegadores". Si no lo hace disponible en IE, nunca estará en todos los navegadores.
km1
la estandarización de manejo no es para todos;) - las empresas van y vienen de nuevo - gracias por citar las probabilidades en el bosque
rápido el
uno más sobre esto: VBA no es una característica constante en todos los navegadores todavía y MS admite constantes en VBA: este es el dominio de canalizar los presupuestos de desarrollo;)
rápido
17

Si no te importa usar funciones:

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

Este enfoque le brinda funciones en lugar de variables regulares, pero garantiza * que nadie puede alterar el valor una vez que se establece.

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

Personalmente, esto me parece bastante agradable, especialmente después de haberme acostumbrado a este patrón de observables noqueados.

* A menos que alguien redefina la función constantantes de que la llame

Hasen
fuente
1
underscore.js implementa una función constante idéntica a este código.
Upperstage
Simple, conciso y responde al espíritu de la pregunta de OP. Esto debería haber recibido más votos positivos.
Mac
3
Esto nunca funcionó realmente para mí. A pesar de que el cierre lo hace inmutable, la var a la que lo asigna todavía se puede sobrescribir. Ej: a = constant(10); a(10); // 10seguido de a = constant(25); a(); //25, no hay errores o advertencias, no hay indicios de que su constante se haya roto.
Patrick M
Si reasigno el valor, aentonces cambiará a un nuevo valor
Saurabh Sharma
17

con la "nueva" Object api puedes hacer algo como esto:

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

Eche un vistazo a esto en el MDN de Mozilla para obtener más detalles. No es una variable de primer nivel, ya que está adjunta a un objeto, pero si tiene un alcance, cualquier cosa, puede adjuntarlo a eso. thisdebería funcionar también. Entonces, por ejemplo, hacer esto en el ámbito global declarará un valor pseudo constante en la ventana (lo cual es una muy mala idea, no debe declarar descuidadamente los valores globales)

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

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

nota: la asignación le devolverá el valor asignado en la consola, pero el valor de la variable no cambiará

Tenshou
fuente
No funciona en safari y en mozilla si ejecuta la instrucción define nuevamente, con un valor diferente, reasignará el valor.
Akshay
2
No 'no funciona en safari', no es compatible con safari. No es el mísmo. Y debería arrojar un 'Error de tipo no capturado: no se puede redefinir la propiedad: <nombre de propiedad aquí>' si lo intenta. o lo estás haciendo mal, o tu ff lo implementó incorrectamente. Supongo que es una mezcla de ambos.
Tenshou
14

Agrupe las constantes en estructuras donde sea posible:

Ejemplo, en mi proyecto de juego actual, he usado a continuación:

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

Asignación:

var wildType = CONST_WILD_TYPES.REGULAR;

Comparacion:

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

Más recientemente estoy usando, para comparar:

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

IE11 es con el nuevo estándar ES6 que tiene una declaración 'const'.
Lo anterior funciona en navegadores anteriores como IE8, IE9 e IE10.

Manohar Reddy Poreddy
fuente
12

Puede equipar fácilmente su script con un mecanismo para constantes que se puede establecer pero no alterar. Un intento de alterarlos generará un error.

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

Olvídate de IE y usa la constpalabra clave.

Derek 朕 會 功夫
fuente
99
¡funciona para mi! pero entonces yo estoy escribiendo una extensión de Chrome, así que sé que estoy en un navegador en su sano juicio ...
yoyo
1
La mejor parte de @yoyo es escribir extensiones y complementos: ¡no es compatible con varios navegadores!
Ian
1
@Ian Bienvenido a 2019, la inconsistencia entre navegadores casi ha desaparecido :)
Fusseldieb
9

Sin embargo, no existe una forma predefinida exacta de navegador cruzado para hacerlo, puede lograrlo controlando el alcance de las variables como se muestra en otras respuestas.

Pero sugeriré usar el espacio de nombre para distinguirlo de otras variables. Esto reducirá la posibilidad de colisión al mínimo de otras variables.

Espacio de nombres adecuado como

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

así que mientras se usa será iw_constant.nameoiw_constant.age

También puede bloquear agregar cualquier clave nueva o cambiar cualquier clave dentro de iw_constant utilizando el método Object.freeze. Sin embargo, no es compatible con el navegador heredado.

ex:

Object.freeze(iw_constant);

Para navegadores más antiguos, puede usar polyfill para el método de congelación.


Si está de acuerdo con la siguiente función de llamada, es la mejor forma de navegador cruzado para definir constante. Alcanzar su objeto dentro de una función de ejecución automática y devolver una función get para sus constantes, por ejemplo:

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

       };

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

// para obtener el valor use iw_constant('name')oiw_constant('age')


** En ambos ejemplos, debe tener mucho cuidado con el espaciado de nombres para que su objeto o función no se reemplace a través de otra biblioteca.

Sudhanshu Yadav
fuente
7

Por un tiempo, especifiqué "constantes" (que todavía no eran realmente constantes) en literales de objetos pasados ​​a las with()declaraciones. Pensé que era muy inteligente. Aquí hay un ejemplo:

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

En el pasado, también he creado un CONSTespacio de nombres donde pondría todas mis constantes. De nuevo, con los gastos generales. Sheesh

Ahora, solo lo hago var MY_CONST = 'whatever';a KISS .

Andrew Hedges
fuente
16
Si hay algo más malvado que eval, definitivamente es with.
NikiC
44
eval es muy malvado! ¡Quemó mi casa una vez!
W3Geek
6

Mi opinión (solo funciona con 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

¡Tratar! Pero entienda: este es un objeto, pero no una variable simple.

Prueba también solo:

const a = 9;
usuario1635543
fuente
5

Yo también he tenido un problema con esto. Y después de bastante tiempo buscando la respuesta y observando todas las respuestas de todos, creo que he encontrado una solución viable para esto.

Parece que la mayoría de las respuestas que he encontrado es usar funciones para mantener las constantes. Como comentan muchos de los usuarios de MUCHOS foros, los usuarios pueden sobrescribir fácilmente las funciones del lado del cliente. La respuesta de Keith Evetts me intrigó de que el exterior no puede acceder al objeto de constantes, sino solo desde las funciones del interior.

Entonces se me ocurrió esta solución:

Ponga todo dentro de una función anónima para que las variables, objetos, etc. no puedan ser cambiados por el lado del cliente. También oculte las funciones 'reales' haciendo que otras funciones llamen a las funciones 'reales' desde adentro. También pensé en usar funciones para verificar si un usuario ha cambiado una función en el lado del cliente. Si se han cambiado las funciones, cámbielas nuevamente usando variables que estén 'protegidas' en el interior y que no se puedan cambiar.

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

También parece que la seguridad es realmente un problema y no hay forma de "ocultar" su programación desde el lado del cliente. Una buena idea para mí es comprimir su código para que sea realmente difícil para cualquiera, incluido usted, el programador, leerlo y comprenderlo. Hay un sitio al que puede ir: http://javascriptcompressor.com/ . (Este no es mi sitio, no se preocupe, no estoy anunciando). Este es un sitio que le permitirá comprimir y ofuscar el código Javascript de forma gratuita.

  1. Copie todo el código en el script anterior y péguelo en el área de texto superior en la página javascriptcompressor.com.
  2. Marque la casilla de verificación Codificar Base62, marque la casilla de verificación Reducir variables.
  3. Presione el botón Comprimir.
  4. Pegue y guárdelo todo en un archivo .js y agréguelo a su página en el encabezado de su página.
Steven Kapaun
fuente
Esta es una buena solución que podría incluirse como una biblioteca para incluir. Pero no me gusta el nombre de sus variables en este código. ¿Por qué descartar los nombres descriptivos como "nombre" y "valor" tal como se usan en el código de Keith? Problema menor, pero aún así.
Cordle
5

Claramente, esto muestra la necesidad de una palabra clave const estandarizada entre navegadores.

Pero por ahora:

var myconst = value;

o

Object['myconst'] = value;

Ambos parecen suficientes y cualquier otra cosa es como disparar una mosca con una bazuca.

codemuncher
fuente
tome el viejo valor var myconst = value; y para la depuración, use un código de depuración adicional ... - funciona como una locura siempre que no todos los navegadores admitan const
Quicker
4

Lo uso en constlugar de varen mis scripts de Greasemonkey, pero es porque solo se ejecutarán en Firefox ... La
convención de nombres también puede ser el camino a seguir (¡hago ambas cosas!).

PhiLho
fuente
4

En JavaScript, mi práctica ha sido evitar las constantes tanto como puedo y usar cadenas en su lugar. Los problemas con las constantes aparecen cuando desea exponer sus constantes al mundo exterior:

Por ejemplo, uno podría implementar la siguiente API de fecha:

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

Pero es mucho más corto y más natural simplemente escribir:

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

De esta manera, los "días" y las "horas" realmente actúan como constantes, porque no puede cambiar desde el exterior cuántos segundos representa "horas". Pero es fácil de sobrescribir MyModule.Date.HOUR.

Este tipo de enfoque también ayudará en la depuración. Si Firebug te dice action === 18que es bastante difícil entender lo que significa, pero cuando lo ves action === "save", está claro de inmediato.

Rene Saarsoo
fuente
Desafortunadamente, es bastante fácil cometer errores ortográficos, por ejemplo, en "Hours"lugar de hacerlo "hours", pero un IDE podría informarle desde el principio que Date.Hoursno está definido.
le_m
4

De acuerdo, esto es feo, pero me da una constante en Firefox y Chromium, una constante inconstante (WTF?) En Safari y Opera, y una variable en IE.

Por supuesto, eval () es malo, pero sin él, IE arroja un error, evitando que se ejecuten los scripts.

Safari y Opera admiten la palabra clave const, pero puede cambiar el valor de const .

En este ejemplo, el código del lado del servidor está escribiendo JavaScript en la página, reemplazando {0} con un 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 qué es bueno esto? No mucho, ya que no es un navegador cruzado. En el mejor de los casos, quizás tenga un poco de tranquilidad de que al menos algunos navegadores no permitirán que los marcadores o los guiones de terceros modifiquen el valor.

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

Desarrollador web
fuente
1
Me encanta ese código! Feo como diablos, pero una buena prueba para el apoyo constante. =)
Stein G. Strindhaug
1
algo gracioso, ¿cuántas líneas puedes escribir para declarar una constante?
rápido
4

Si vale la pena mencionar, puede definir constantes en angular usando$provide.constant()

angularApp.constant('YOUR_CONSTANT', 'value');
Muhammad Reda
fuente
... y puedes usar const en VBA ... xbrowser? ... ups ...;)
rápido
OP pregunta sobre javascript, responde ofertas con un marco JS específico muy obstinado. Prácticamente fuera de tema.
Rounce
2
@rounce: Off-topic respuestas siguen siendo respuestas, no la bandera como no una respuesta , pero downvote y voto para eliminar su lugar. Consulte ¿Cómo uso correctamente el indicador "No es una respuesta"?
Kevin Guan
@KevinGuan Notado, lo hará en el futuro.
Rounce
4

Una versión mejorada de la respuesta de Burke que te permite hacer en CONFIG.MY_CONSTlugar de CONFIG.get('MY_CONST').

Requiere IE9 + o un navegador 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;
}());

* Las propiedades son de solo lectura, solo si los valores iniciales son inmutables.

Şafak Gür
fuente
4

JavaScript ES6 (re) introdujo la constpalabra clave que es compatible con todos los principales navegadores .

Las variables declaradas vía constno se pueden volver a declarar o reasignar.

Aparte de eso, se constcomporta de manera similar a let.

Se comporta como se espera para los tipos de datos primitivos (booleano, nulo, indefinido, número, cadena, símbolo):

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

Atención: tenga en cuenta las dificultades con respecto a los 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

Si realmente necesita un objeto inmutable y absolutamente constante: solo use const ALL_CAPSpara aclarar su intención. De todos constmodos, es una buena convención para todas las declaraciones, así que confíe en ella.

le_m
fuente
Solo desde IE11 :-(
Mo.
3

Otra alternativa es 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);
}

Entonces simplemente: var foo = constantMap.MY_CONSTANT

Si constantMap.MY_CONSTANT = "bar"lo hiciera, no tendría ningún efecto, ya que estamos tratando de usar un operador de asignación con un captador, por constantMap.MY_CONSTANT === "myconstant"lo tanto, seguiría siendo cierto.

rodeo
fuente
3

en Javascript ya existen constantes . Define una constante como esta:

const name1 = value;

Esto no puede cambiar mediante la reasignación.

Erik Lucio
fuente
Según el enlace en la respuesta, esta es una característica experimental y debe usarse con precaución.
Johnie Karr
Por supuesto, estoy de acuerdo contigo. Pero en las últimas versiones de navegadores funciona.
Erik Lucio
3

La palabra clave 'const' se propuso anteriormente y ahora se ha incluido oficialmente en ES6. Al usar la palabra clave const, puede pasar un valor / cadena que actuará como una cadena inmutable.

Ritumoni Sharma
fuente
2

Introducir constantes en JavaScript es, en el mejor de los casos, un truco.

Una buena manera de hacer valores persistentes y accesibles globalmente en JavaScript sería declarar un objeto literal con algunas propiedades de "solo lectura" como esta:

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

tendrás todas tus constantes agrupadas en un solo objeto accesorio "mi" donde puedes buscar tus valores almacenados o cualquier otra cosa que hayas decidido poner allí para el caso. Ahora probemos si funciona:

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

Como podemos ver, la propiedad "my.constant1" ha conservado su valor original. Te has hecho algunas buenas constantes temporales 'verdes' ...

Pero, por supuesto, esto solo lo protegerá de modificar, alterar, anular o vaciar accidentalmente el valor constante de su propiedad con un acceso directo como en el ejemplo dado.

De lo contrario, sigo pensando que las constantes son para tontos. Y sigo pensando que intercambiar su gran libertad por un pequeño rincón de seguridad engañosa es el peor intercambio posible.

Bill el lagarto
fuente
2

Rhino.jsimplementa constademás de lo mencionado anteriormente.

isomorfismos
fuente