JavaScript中有常量吗?


1132

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

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


35
Chrome允许您使用关键字const来使用常量。例如const ASDF = "asdf"。但是,由于const不兼容多浏览器,因此我通常坚持var声明。
Jacksonkr 2011年

20
try{const thing=1091;}catch(e){var thing=1091;}作品。
德里克·朕会功夫2012年

13
Derek:您的try / catch不会将您要声明的内容的范围限制在try / catch块中吗?如果您的范围设定不正确,那么指定constvar根本没有意义?
Coderer

8
在当前实现中,@ Coderer可以正常工作,因为const它的作用域与相同var,并且是功能级的,而不是块级的。如果您改为遵循即将发布的ECMAScript标准,const则其范围与相同let,这意味着它将无法使用。
贾斯珀

3
@Coderer语言错误。javascript中的变量是函数范围。这不是C.
doug65536

Answers:


1018

ES2015起,JavaScript的概念是const

const MY_CONSTANT = "some-value";

几乎可以在除IE 8、9和10之外的所有浏览器中使用。有些可能还需要启用严格模式

您可以var与ALL_CAPS之类的约定一起使用,以表明如果需要支持旧版浏览器或使用旧版代码,则不应修改某些值:

var MY_CONSTANT = "some-value";

60
const x = 24怎么样?
扎卡里·斯科特

93
请注意,如果不需要跨浏览器的兼容性(或者您在Rhino或Node.js中进行服务器端编程),则可以使用const关键字。目前,除IE之外,所有现代浏览器均支持该功能。
赫斯基

17
这些天(3.5年后)可以Object.defineProperty用来创建也不能删除的只读属性。这适用于所有主要浏览器的当前版本(但在IE8中不正确)。请参阅@NotAName的答案
Phrogz 2012年

12
@Amyth并没有真正的帮助。这是唯一供应商提出的样式指南。根据以上Husky的观点,编写服务器端JS时IE兼容性完全不相关。
13年

32
由于该答案在2015年仍被Google高度评价,因此应该说它已经过时了。const现在,该关键字已正式成为该语言的一部分,并且每个浏览器都支持该关键字。根据statcounter.com的说法,只有百分之几的互联网用户仍在使用不支持的旧浏览器版本const
tristan 2015年

310

您是否要保护变量不被修改?如果是这样,则可以使用模块模式:

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的约定。


13
请注意,您可以只返回CONFIG值的函数。这样可以节省您一直调用CONFIG.get()的时间。
Mathew Byrne

4
漂亮的解决方案。但是这些东西应该包装成一个库,以免在任何新项目中重塑它们。
andrii

82
CONFIG.get = someNewFunctionThatBreaksTheCode...总之,您绝对不能在JS中执行常量(不带const关键字)。您唯一能做的就是限制可见度。
Thomas Eding

28
我确实相信这private是JavaScript中将来的保留字,如果您是我,我不会使用它。
Zaq 2012年

这也是注册表模式。

122

const关键字是ECMAScript的第6条草案,但迄今只享受的浏览器支持一知半解:http://kangax.github.io/compat-table/es6/。语法为:

const CONSTANT_NAME = 0;

13
如果您尝试为分配一个值const,则不会引发任何错误。赋值只是失败,并且常量仍然具有其原始值。恕我直言,这是一个主要的设计缺陷,但只要有一个清晰,一致的命名约定(例如流行的ALL_CAPS),我认为它不会引起太多的麻烦。
MatrixFrog 2010年

6
请在此处关注浏览器支持:kangax.github.io/es5-compat-table/es6/#const
Mark McDonald

6
@MatrixFrog分配将引发错误'use strict'
萨姆(Sam)2015年

我应该在中定义常量ALL CAPS吗?
刘易斯

1
@Tresdin在所有大写字母中定义常量是一种常见的命名约定。语言规范中没有什么强制要求这样做的,但这并不是一个坏主意。它使您的意图更加清晰,从而提高了代码的可读性。
比尔蜥蜴2015年

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

参见Object.freeze。如果您还希望将引用设为只读,则可以使用constconstants


2
应该提到的是,这仅适用于IE9 + kangax.github.io/compat-table/es5
Cordle 2014年

如果没有实施失败的话,我会i
Alnitak

注意:这与ES6 const声明的行为类似,例如,不能重新声明或重新分配属性,但是如果属性属于datatype object,则可以对其进行突变。
le_m

正是我想要的。您也可以使用const constants代替var constants来防止重新分配变量。
Jarett Millard

参见例如深度冻结以进行递归冻结。
SAM

64

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>

50
伙计,说说一些不是跨浏览器的东西。。。仍需+1,以便在框外思考。
汤姆

14
VBScript?那是什么?;)
tybro0103 2013年

2
我通常会为通用相关的跨浏览器问题投票,并提供IE特定答案。因为我讨厌那些认为IE javascript实现是“一个”的人,而其他人则被忽略。顺便说一句,谁正在使用除IE之外的其他浏览器?
2013年

@Cooluhuru该脚本似乎可以处理IE浏览器(使用VBScript)和非IE浏览器(使用JavaScript const)。您能解释一下这是怎么回事吗?
安德鲁·格林

我仍然很难接受可以更改常量。
诺伯特·诺伯森

59

ECMAScript 5确实引入了Object.defineProperty

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

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

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


1
值得注意的是,这不像传统常量。这将仅允许您定义(非常量对象的)常量属性。同样,这不会产生错误,甚至会返回您尝试设置的值。它只是不写值。
Cory Gross

3
最近,我读的是试图分配给属性与writable: false 如果这样做分配的代码正在下的ECMAScript 5的严格模式解释居然抛出一个错误。编写'use strict'代码的另一个原因。
科里·格罗斯

6
实际上writable: false,您可以省略,因为这是默认设置
2014年

24

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


@John指出了一种在其他语言上已经使用了多年的const命名惯例,我认为没有理由不能使用它。当然,这并不意味着某人无论如何也不会覆盖变量的值。:)


11
众所周知,如果IE无法实现,那么它也可能不存在。
乔什·辛曼

3
不幸的是,实际上,这是事实。IE确实拥有巨大的市场份额。如果我拥有一家公司并在内部使用Web应用程序,那么我将对FF进行标准化。我不知道为什么这么多人在乎IE,这真是吹牛。
詹森·邦廷

@Rich:谁说我的观点是事实?您做了相当的假设。此外,就我而言,IE很烂是事实。您可以拥有自己的事实,我不是说您必须相信我的事实。:P拿Xanax或其他东西...
詹森·邦廷

@Rich B,是的,这只是一个愚蠢的评论,相信我,我会说很多愚蠢的评论。@Jason B.-有趣的是,昨晚我遇到了这个问题。.const在FF中工作,但在IE中没有。感谢您的澄清

谁在乎IE?我不!FF,Chrome或Opera等...几乎可以安装在每个OS平台上。此外,计算机零售商通常也知道旧版IE很烂,因此他们经常(甚至每次)在销售计算机之前安装其他浏览器。因此,我决定让我开发的应用程序根本不关心不兼容的浏览器:如果浏览器开发人员在乎遵守其产品可以使用我的应用程序的标准,否则,用户将使用其他浏览器...我可以使用它; -)但是Microsoft可以活着失去部分市场吗?不,他们不能这样做,因此“他们”将改变他们的开发政策!
威利·旺卡

20

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

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


alert(MY_CONSTANT());

6
值得指出的是,这属于@Burkes答案(@trinithis'评论)中提到的相同问题。MY_CONSTANT = function(){返回“其他值”; 打破它。+1虽然不错,却是快速的解决方案。
Patrick M

13
-1。这与var SOME_NAME = value(仍然可变)无关,它是更多代码,需要解释。
mikemaccana 2013年

@PatrickM确实可以修改这种伪常量,但是在其他语言(例如C)中,您不能修改常量,您仍然可以通过指针进行修改。因此,只要您使用某种方法至少表明它是一个常数,就可以了。
修订

20

Mozillas 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等)。因此,var或中没有区别function(){return}const是唯一的实常数。

更新:IE11 支持 const

IE11包括用于新兴的ECMAScript 6标准的明确定义和常用的功能,包括让,支承constMapSet,和WeakMap,以及__proto__改进的互操作性。


24
“它从未在所有浏览器上都可用”。如果您不让它在IE中可用,那么它将永远不会在所有浏览器中使用。
km1 2012年

驾驶标准化并不适合每个人;)-公司来了又又去了-谢谢您引用赔率的报价
Quicker

进一步说明:VBA并不是所有浏览器都具有共识功能,MS在VBA中支持const-这是对开发预算的精通;)
更快的

17

如果您不介意使用函数:

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

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

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

我个人觉得这很令人愉快,尤其是在从可观察的观测器适应了这种模式之后。

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


1
underscore.js实现了与此代码相同的常量函数。
2014年

简单,简洁并回答了OP问题的精神。这本应获得更多upVotes。
Mac

3
这从来没有真正为我工作。即使闭包使其不可变,但您为其分配的var仍可以被覆盖。例如:a = constant(10); a(10); // 10后跟a = constant(25); a(); //25,没有错误或警告,没有表明您的常量已损坏。
Patrick M

如果我将值重新分配给a它,那么它将更改为新值
Saurabh Sharma

17

使用“新”对象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

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


如果您再次执行define语句(使用不​​同的值),则无法在Safari和Mozilla中工作,它将重新分配该值。
阿克沙伊

2
Safari浏览器不支持 “不能在Safari浏览器中工作” 。不一样。如果尝试这样做,它将引发“未捕获的TypeError:无法重新定义属性:<此处的属性名称”。您做错了,或者您的ff错误地实施了它。我想这是两者的结合。
tenshou

14

在可能的情况下将常量分组为结构:

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

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带有带有“ const”声明的新ES6标准。
以上适用于IE8,IE9和IE10等较早的浏览器。


12

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

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

12

忘记IE并使用const关键字。


9
为我工作!但是后来我正在写一个chrome扩展程序,所以我知道我在使用理智的浏览器...
yoyo

1
@yoyo有关编写扩展和插件的最佳部分-不支持跨浏览器!
伊恩2014年

1
@Ian欢迎来到2019,跨浏览器的不一致几乎消失了:)
Fusseldieb

9

但是,尚无精确的跨浏览器预​​定义方法来执行此操作,您可以通过控制变量的范围来实现它,如其他答案所示。

但是我建议使用命名空间来区别其他变量。这会将与其他变量发生碰撞的机会降到最低。

正确的命名空间,例如

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进行冻结。


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


**在这两个示例中,您都必须非常小心地注意名称间距,以免对象或函数被其他库替换(如果对象或函数本身将被替换,则整个常量将消失)


7

有一阵子,我在传递给with()语句的对象常量中指定了“常量”(实际上并不是常量)。我以为它很聪明。这是一个例子:

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

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

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


16
如果有比邪恶更邪恶的事情,那肯定是with
NikiC 2011年

4
评估是非常邪恶的!它一次烧毁了我的房子!
W3Geek

6

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

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;

5

我也有这个问题。在寻找答案并查看每个人的所有回答之后,我想我已经找到了一个可行的解决方案。

看来,我遇到的大多数答案都是使用函数来保存常量。正如许多论坛的许多用户所张贴的那样,客户端的用户可以很容易地覆盖这些功能。基思·埃维茨(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页面上的顶部文本区域中。
  2. 选中“ Base62编码”复选框,选中“缩小变量”复选框。
  3. 按压缩按钮。
  4. 将所有内容粘贴并保存到.js文件中,然后将其添加到页面顶部的页面中。

这是一个很好的解决方案,可以很好地包装为要包含的库。但是我不喜欢在此代码中为您的变量命名。为什么要删除基思代码中使用的描述性名称,例如“名称”和“值”?次要问题,但仍然存在。
Cordle 2014年

5

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

但现在:

var myconst = value;

要么

Object['myconst'] = value;

两者似乎都足够,其他一切都像用火箭筒射击苍蝇。


取好旧的var myconst = value; 并使用额外的调试代码进行调试...-并非所有浏览器都支持const一样疯狂
更快

4

我在Greasemonkey脚本中使用const而不是var,但是,因为它们只能在Firefox上运行...
名称约定确实也是可行的方式(我俩都做!)。


4

在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"便会立即清楚。


不幸的是,很容易犯拼写错误-例如,"Hours"而不是"hours"-但IDE可能会在Date.Hours未定义的早期就让您知道。
le_m

4

好的,这很丑陋,但是它为我提供了Firefox和Chromium中的常量,Safari和Opera中的常量(WTF?),以及IE中的变量。

当然eval()是邪恶的,但是如果没有它,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 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);

这有什么用?不多,因为它不是跨浏览器。充其量,也许至少有些省心浏览器不会让bookmarklet或第三方脚本修改该值,这样可以让您。

经过Firefox 2、3、3.6、4,Iron 8,Chrome 10、12,Opera 11,Safari 5,IE 6、9的测试。


1
喜欢那个代码!丑陋,但是对const支持的很好测试。=)
Stein G. Strindhaug 2011年

1
有点有趣,是的-您可以键入几行来声明const?
更快的

4

如果值得一提的,你可以定义常量的角度使用$provide.constant()

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

...而且您可以在VBA中使用const ... xbrowser?... ups ...;)
更快

OP问有关javascript的问题,并回答带有特定观点的JS框架。几乎没有话题。
反弹

2
@rounce:题外话答案仍然是答案,不标记他们作为不是一个答案,但downvote投票删除代替。请参阅如何正确使用“ Not a Answer”标志?
凯文·关

@KevinGuan注意,将来会做。
反弹

4

Burke答案的改进版本,可让您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;
}());

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


4

JavaScript ES6(重新)引入了所有主流浏览器都支持的const关键字

通过声明的变量const无法重新声明或重新分配。

除此之外,其const行为类似于let

对于基本数据类型(布尔,空,未定义,数字,字符串,符号),它的行为符合预期:

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无论如何都要遵循所有声明是一个好习惯,因此请仅依赖它。


仅来自IE11:-(

3

另一种选择是:

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"将保持不变。



3

关键字“ const”是较早提出的,现在已正式包含在ES6中。通过使用const关键字,您可以传递将作为不可变字符串的值/字符串。


2

在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”属性保留了其原始值。您已经为自己设置了一些不错的“绿色”临时常量...

但是,当然,这只能防止您通过直接访问意外地修改,更改,无效或清空属性常量值,如给定示例所示。

否则我仍然认为常量是假的。我仍然认为,将自己的巨大自由换成一小部分欺骗性安全保障是最糟糕的交易。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.