JavaScript中有常量吗?

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

如果不是,那么指定用作常量的变量的常见做法是什么?

512746 次浏览

不,不是一般的。Firefox实现了const,但我知道IE没有。


<强>@约翰指向了在其他语言中已经使用多年的consts的常见命名实践,我认为你没有理由不能使用它。当然,这并不意味着有人无论如何都不会写变量的值。:)

ES2015开始,JavaScript有#0的概念:

const MY_CONSTANT = "some-value";

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

您可以将var与ALL_CAPS等约定一起使用,以表明如果您需要支持旧浏览器或正在使用遗留代码,则不应修改某些值:

var MY_CONSTANT = "some-value";

我使用const而不是var在我的Gasemonkey脚本中,但这是因为它们只会在Firefox上运行…
名称约定确实可以走的路,太(我都做!)。

有一段时间,我在传递给with()语句的对象文字中指定了“常量”(实际上仍然不是常量)。我认为这很聪明。这是一个例子:

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

在过去,我还创建了一个CONST命名空间,我将在其中放置我所有的常量。同样,开销。嘘。

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

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

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';                 // erroralert('MY_CONST: ' + CONFIG.get('MY_CONST'));  // 1

使用这种方法,不能修改值。但是,您必须在CONgraph:(上使用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>

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

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

alert(MY_CONSTANT());

ECMAScript 5确实引入了#0

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

它是所有现代浏览器都支持(以及IE≥9)。

另见:Object.defineES5?

在JavaScript中,我的做法是尽可能避免使用常量,而是使用字符串。当你想向外界公开你的常量时,常量会出现问题:

例如,可以实现以下Date API:

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

但它更短,更自然,简单地写:

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

这样,“天”和“小时”实际上就像常量一样,因为您无法从外部更改“小时”代表多少秒。但很容易覆盖MyModule.Date.HOUR

这种方法也有助于调试。如果Firebug告诉您action === 18,很难弄清楚它的含义,但当您看到action === "save"时,它会立即清楚。

您可以轻松地为您的脚本配备一种可以设置但不能更改的常量机制。试图更改它们将产生错误。

/* author Keith Evetts 2009 License: LGPLanonymous 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 generatedthey 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 VATtry{SETCONST( 'VAT', 0.22 );} catch ( exc )  {alert (exc.message);}//check old value of VAT remainsalert( CONST('VAT') );

// try to get at constants object directlyconstants['DODO'] = "dead bird";  // error

Mozillas MDN Web文档包含关于const的好例子和解释。摘录:

// define MY_FAV as a constant and give it the value 7const 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、#0MapSetWeakMap,以及用于改进互操作性的__proto__

好吧,这是丑陋的,但它给了我一个在Firefox和Chromium中的常量,一个在Safari和Opera中的常量(WTF?),以及一个在IE中的变量。

当然ava()是邪恶的,但没有它,IE会抛出错误,阻止脚本运行。

Safari和Opera支持const关键字,但是你可以改变const的值

在此示例中,服务器端代码正在将JavaScript写入页面,将{0}替换为值。

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 silentlyalert('err1 '+err1);}alert('const '+FOO);if(FOO=='?NO!'){// changed in Sf/Op - set back to original valueFOO=original;}}catch(err2){// IE failalert('err2 '+err2);// set var (no var keyword - Chrome/Firefox complain about redefining const)FOO='{0}';alert('var '+FOO);}alert('FOO '+FOO);

这有什么好处?不多,因为它不是跨浏览器的。充其量,也许有点安心,至少一些浏览器不会让书签或第三方脚本修改值。

测试与Firefox 2,3,3.6,4,铁8,Chrome10,12,歌剧11,Safari5, IE 6,9。

忘记IE并使用const关键字。

将常量引入JavaScript充其量是一种黑客行为。

在JavaScript中创建持久且全局可访问的值的一个好方法是声明一个具有一些“只读”属性的对象文字,如下所示:

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

你将把所有常量分组在一个“我的”附件对象中,你可以在其中查找存储的值或任何其他你可能决定放在那里的东西。现在让我们测试它是否有效:

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

正如我们所看到的,“my.constant1”属性保留了它的原始值。

但当然,这只会防止您意外修改、更改、取消或清空您的属性常量值,如给定示例中的直接访问。

否则我仍然认为常量是傻瓜。我仍然认为,用你的巨大自由换取欺骗性安全的一小部分是最糟糕的交易。

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

似乎我遇到的大多数答案都是使用函数来保存常量。正如MANY论坛的许多用户所说,客户端的用户可以很容易地编写函数。我对基思·埃维茨的回答很感兴趣,即常量对象不能被外部访问,只能从内部的函数访问。

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

把所有的东西都放在匿名函数里面,这样客户端就无法更改变量,对象等。也可以通过让其他函数从内部调用“真实”函数来隐藏“真实”函数。我还想过用函数来检查客户端的用户是否修改了函数。如果函数被修改了,用内部“保护”且无法更改的变量将它们更改回来。

/*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 textof the error messages.*/
//object literal to hold the constantsvar 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 hasto 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'tsee any of your coding call this function. You call the _makeDef() in your code and that function callsthis 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 thisfunction. The argument 't' is the name of the const and doesn't need to be all caps because I set itto upper case within the function, 'y' is the value of the value of the const and has to exist. Imake 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. Theargument 's' is the name of the const and doesn't need to be all capse because I set it to upper casewithin the function. I make a different variable to make it harder for a user to figure out whats goingon. The function returns the _access function call. I pass the new variable and the original stringalong to the _access function. I do this because if a user is trying to get the value of something, ifthere is an error the argument doesn't get displayed with upper case in the error message. You call thisfunction 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 throughthis function. The argument 'g' is the name of the const and its all upper case, 'f' is also the nameof the const, but its the original string that was passed to the _getDef() function. If there is anerror, the original string, 'f', is displayed. This makes it harder for a user to figure out how theconstants are being stored. If there is a property with the same name in the object holder, we returnthe constant value. If not, we check if the 'f' variable exists, if not, set it to the value of 'g' andthrow an error. This is a 'hidden' function and the user doesn't see any of your coding call thisfunction. 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 thefunctions inside this anonymous function. These variables are strings of the four above functions andwill be used by the all-dreaded eval() function to set them back to their original if any of them shouldbe 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 willcheck if a specific line of code is inside a given function. If it is, then we do nothing, if not, thenwe use the eval() function to set the function back to its original coding using the function stringvariables above. This function will also throw an error depending upon the doError variable being set to trueThis is a 'hidden' function and the user doesn't see any of your coding call this function. You call thedoCodeCheck() function and that function calls this function.    -    You can change the error messages towhatever 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 differentvariable to make it harder for a user to figure out whats going on. You call this function in your code to checkif 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页面的顶部文本区域。
  2. 选中Base62编码复选框,选中收缩变量复选框。
  3. 按下压缩按钮。
  4. 将其全部粘贴并保存在. js文件中,并将其添加到页面头部的页面中。

我的观点(仅适用于对象)。

var constants = (function(){var a = 9;
//GLOBAL CONSTANT (through "return")window.__defineGetter__("GCONST", function(){return a;});
//LOCAL CONSTANTreturn {get CONST(){return a;}}})();
constants.CONST = 8; //9alert(constants.CONST); //9

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

也试试:

const a = 9;

使用“new”对象api,您可以这样做:

var obj = {};Object.defineProperty(obj, 'CONSTANT', {configurable: falseenumerable: 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

注意:赋值会在控制台中返回赋值,但变量的值不会改变

除了上面提到的之外,Rhino.js还实现了const

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

但就目前而言:

var myconst = value;

Object['myconst'] = value;

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

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

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

正确的命名空间,如

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

对于较旧的浏览器,您可以使用聚填充进行冻结方法。


如果您可以调用函数,以下是定义常量的最佳跨浏览器方法。在自执行函数中定义对象并为您的常量返回一个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')


**在这两个例子中,你必须非常小心名称行间距,这样你的对象或函数就不应该被其他库替换。(如果对象或函数本身被替换,你的整个常量就会消失)

const关键字在javcript语言中可用,但它不支持IE浏览器。支持其余浏览器。

如果你不介意使用函数:

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

这种方法为您提供函数而不是常规变量,但它保证*没有人可以在设置后更改值。

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

我个人觉得这相当愉快,特别是在习惯了这种模式之后。

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

"use strict";
var constants = Object.freeze({"π": 3.141592653589793 ,"e": 2.718281828459045 ,"i": Math.sqrt(-1)});
constants.π;        // -> 3.141592653589793constants.π = 3;    // -> TypeError: Cannot assign to read only property 'π' …constants.π;        // -> 3.141592653589793
delete constants.π; // -> TypeError: Unable to delete property.constants.π;        // -> 3.141592653589793

请参见Object.freeze。如果您想将constants引用也设为只读,您可以使用使用#0

另一种选择是这样的:

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

简单地说:var foo = constantMap.MY_CONSTANT

如果你是constantMap.MY_CONSTANT = "bar",它将没有效果,因为我们试图使用一个带有getter的赋值操作符,因此constantMap.MY_CONSTANT === "myconstant"将保持为true。

伯克的回答的改进版本,可让您执行CONFIG.MY_CONST而不是CONFIG.get('MY_CONST')

它需要IE9+或真正的Web浏览器。

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

*属性是只读的,仅当初始值不可变时。

如果值得一提,您可以使用#0角度中定义常量

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

Checkouthttps://www.npmjs.com/package/constjs,它提供了三个函数来创建枚举、字符串const和位图。返回的结果是冻结密封,因此您不能在创建属性后更改/删除它们,也不能向返回的结果添加新属性

创建枚举:

var ConstJs = require('constjs');
var Colors = ConstJs.enum("blue red");
var myColor = Colors.blue;
console.log(myColor.isBlue()); // output trueconsole.log(myColor.is('blue')); // output trueconsole.log(myColor.is('BLUE')); // output trueconsole.log(myColor.is(0)); // output trueconsole.log(myColor.is(Colors.blue)); // output true
console.log(myColor.isRed()); // output falseconsole.log(myColor.is('red')); // output false
console.log(myColor._id); // output blueconsole.log(myColor.name()); // output blueconsole.log(myColor.toString()); // output blue
// See how CamelCase is used to generate the isXxx() functionsvar AppMode = ConstJs.enum('SIGN_UP, LOG_IN, FORGOT_PASSWORD');var curMode = AppMode.LOG_IN;
console.log(curMode.isLogIn()); // output trueconsole.log(curMode.isSignUp()); // output falseconsole.log(curMode.isForgotPassword()); // output false

创建字符串const:

var ConstJs = require('constjs');
var Weekdays = ConstJs.const("Mon, Tue, Wed");console.log(Weekdays); // output {Mon: 'Mon', Tue: 'Tue', Wed: 'Wed'}
var today = Weekdays.Wed;console.log(today); // output: 'Wed';

创建位图:

var ConstJs = require('constjs');
var ColorFlags = ConstJs.bitmap("blue red");console.log(ColorFlags.blue); // output false
var StyleFlags = ConstJs.bitmap(true, "rustic model minimalist");console.log(StyleFlags.rustic); // output true
var CityFlags = ConstJs.bitmap({Chengdu: true, Sydney: false});console.log(CityFlags.Chengdu); //output trueconsole.log(CityFlags.Sydney); // output false
var DayFlags = ConstJs.bitmap(true, {Mon: false, Tue: true});console.log(DayFlags.Mon); // output false. Default val wont override specified val if the type is boolean

欲了解更多信息,请结帐

声明:我是这个工具的作者。

在Javascript中已经存在常数。你定义一个像这样的常量:

const name1 = value;

这不能通过重新分配来改变。

尽可能将常量分组到结构中:

例如,在我目前的游戏项目中,我使用了以下内容:

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 herebreak;case CONST_WILD_TYPES.EXPANDING:// do something herebreak;}

IE11是新的ES6标准,具有“const”声明。
以上适用于早期的浏览器,如IE8、IE9和IE10。

关键字'const'早些时候提出,现在它已正式包含在ES6中。通过使用const关键字,您可以传递一个将充当不可变字符串的值/字符串。

JavaScript ES6(re-)引入了所有主要浏览器中支持的#0关键字

通过const声明的变量不能重新声明或重新分配。

除此之外,const的行为类似于

它的行为符合原始数据类型(布尔、空、未定义、数字、字符串、符号)的预期:

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

注意事项:要注意关于对象的陷阱:

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

如果你真的需要一个不可变且绝对不变的对象:只需使用const ALL_CAPS来明确你的意图。无论如何,这是所有const声明都要遵循的一个很好的约定,所以只需依赖它。

声明一个名为constatnt的只读。

通过const声明的变量不能重新声明或重新分配。

常量可以用大写或小写声明,但常见的使用全大写字母

// const c;// c = 9;   //intialization and declearation at same placeconst c = 9;// const c = 9;// re-declare and initialization is not possibleconsole.log(c);//9