JavaScript中有常量吗?

有没有办法在JavaScript中使用常量?

如果没有,指定用作常量的变量的常用做法是什么?

最新版本的JavaScript ES2015有一个const的概念:

 const MY_CONSTANT = "some-value"; 

这将工作在几乎所有的浏览器,除了IE 8,9和10 。 有些可能还需要严格模式启用。

如果您不写ES2015代码,您可以使用ALL_CAPS这样的约定来显示某些值不应该被修改:

 var MY_CONSTANT = "some-value"; 

你是否试图保护变量不被修改? 如果是这样,那么你可以使用模块模式:

 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 

使用这种方法,值不能被修改。 但是,你必须在CONFIG :()上使用get()方法。

如果你不需要严格保护变量的值,那就按照建议使用ALL CAPS的惯例。

const关键字在ECMAScript 6草案中,但是到目前为止,只有少数浏览器支持: http : //kangax.github.io/compat-table/es6/ 。 语法是:

 const CONSTANT_NAME = 0; 

IE确实支持常量,比如:

 <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> 
 "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 

见Object.freeze 。 如果你想使constants引用只读,你可以使用const

ECMAScript 5确实引入了Object.defineProperty

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

它支持每个现代浏览器 (以及IE≥9)。

另请参阅: ES5中的Object.defineProperty?

不,一般来说。 Firefox实现const但我知道IE不。


@John指出了常用于其他语言的常用命名惯例,我没有理由不能使用它。 当然,这并不意味着有人不会写出变量的值。 🙂

Mozilla的MDN Web Docs包含了关于const很好的例子和解释。 摘抄:

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

但是,IE9 / 10仍然不支持const 。 而这是荒谬的原因:

那么,什么是IE9与const做? 到目前为止,我们的决定是不支持它。 它还不是一个共识特征,因为它在所有的浏览器中从未有过。

最后,对于网络来说,最好的长期解决方案似乎是放弃,并等待标准化进程顺利进行。

他们没有实现它,因为其他浏览器没有正确实现它?! 害怕做得更好? 标准的定义与否,一个常数是一个常数:设定一次,永不改变。

对于所有的想法:每个功能都可以被覆盖(XSS等)。 所以在varfunction(){return}没有区别。 const是唯一真正的常量。

更新:IE11 支持 const

IE11包含对新兴的ECMAScript 6标准(包括let, constMapSetWeakMap )以及__proto__的良好定义和常用特征的WeakMap ,以提高互操作性。

在JavaScript中,我的首选是使用函数来返回常量值。

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

如果你不介意使用函数:

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

这种方法给你的函数,而不是常规变量,但它保证*一旦设置,没有人可以改变的价值。

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

我个人觉得这很愉快,特别是在习惯了这个模式之后,从淘汰赛的可观察到的。

*除非有人在调用函数之前重新定义了函数constant

与“新”对象api,你可以做这样的事情:

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

请参阅Mozilla MDN以了解更多细节。 这不是第一级变量,因为它附加到一个对象,但是如果你有一个范围,任何东西,你可以把它附加到这个。 this应该工作。 因此,举例来说,在全局范围内执行此操作将在窗口中声明一个伪常量值(这是一个非常糟糕的主意,您不应该不小心声明全局变量)

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

注意:赋值会让你回到控制台的赋值,但变量的值不会改变

将常量组合到可能的结构中:

例如,在我目前的游戏项目中,我已经在下面使用了:

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

分配:

 var wildType = CONST_WILD_TYPES.REGULAR; 

比较:

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

最近我用来比较:

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

IE11是新的ES6标准,有'const'声明。
以上在IE8,IE9和IE10浏览器的作品。

您可以轻松地为您的脚本提供一个可以设置但不能更改的常量机制。 试图改变它们会产生一个错误。

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

然而,没有确切的跨浏览器预​​定义的方式来做到这一点,你可以通过控制其他答案中显示的变量范围来实现。

但我会建议使用名称空间来区分其他变量。 这会将碰撞的几率从其他变量减到最小。

适当的命名空间就像

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

所以当使用它将是iw_constant.nameiw_constant.age

您还可以使用Object.freeze方法阻止添加任何新键或更改iw_constant中的任何键。 但是,旧版浏览器不支持它。

例如:

 Object.freeze(iw_constant); 

对于较旧的浏览器,您可以使用polyfill作为冻结方法。


如果你确定调用函数如下是最好的跨浏览器的方式来定义常量。 在一个自动执行的函数中定义你的对象,并为你的常量返回一个get函数。例如:

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

//获取值使用iw_constant('name')iw_constant('age')


**在这两个例子中,你必须非常小心的名字空间,以便你的对象或函数不应该被其他库替换(如果对象或函数本身将被替换,你的整个常量将会去)

有一段时间,我在通过with()语句传递的对象字面量中指定了“常量”(实际上并不是常量)。 我以为这是如此聪明。 这是一个例子:

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

在过去,我也创建了一个CONST命名空间,我将所有的常量。 再次,与开销。 啧。

现在,我只是做var MY_CONST = 'whatever'; 到KISS 。

我的意见(只适用于对象)。

 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 

尝试! 但理解 – 这是对象,但不是简单的变量。

也尝试只是:

 const a = 9; 

忘记IE并使用const关键字。

我也有这个问题。 经过了一段时间寻找答案,并看到每个人的所有反应,我想我已经想出了一个可行的解决方案。

看来我所遇到的大部分答案是使用函数来保存常量。 由于很多MANY论坛的用户发帖,这些功能很容易被客户端的用户覆盖。 我对基思·伊维特(Keith Evetts)的回答感兴趣,即常数对象不能被外部访问,而只能来自内部的函数。

所以我想出了这个解决方案:

把所有内容都放在一个匿名函数中,这样变量,对象等不能被客户端改变。 也可以通过其他函数从内部调用“真实”函数来隐藏“真实”函数。 我也想过使用函数来检查一个函数是否被客户端的用户改变了。 如果功能已经更改,请使用内部受保护的变量将其更改回来,并且不能更改。

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

安全性似乎也是一个问题,并且没有办法从客户端“隐藏”你的编程。 对我来说,一个好主意是压缩你的代码,这样包括你,程序员在内的任何人都难以阅读和理解它。 有一个网站,你可以去: http : //javascriptcompressor.com/ 。 (这不是我的网站,不要担心,我不是广告。)这是一个网站,可以让你免费压缩和混淆Javascript代码。

  1. 复制上述脚本中的所有代码,并将其粘贴到javascriptcompressor.com页面顶部的textarea上。
  2. 检查Base62编码复选框,检查收缩变量复选框。
  3. 按压缩按钮。
  4. 粘贴并将其全部保存在.js文件中,并将其添加到页面头部的页面中。

显然这表明需要一个标准化的跨浏览器const关键字。

但现在:

 var myconst = value; 

要么

 Object['myconst'] = value; 

两者似乎都足够了,其他任何事情都像用火箭筒射击苍蝇。

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

I use const instead of var in my Greasemonkey scripts, but it is because they will run only on Firefox…
Name convention can be indeed the way to go, too (I do both!).

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.

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.

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.

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.

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

const keyword available in javscript language but it does not support IE browser. Rest all browser supported.

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.