JavaScript 中有常量吗?

1179

JavaScript中是否有使用常量的方法?

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


14
Derek问道:你的try/catch会限制你在try/catch块中声明的变量的作用域吗?如果你没有正确地进行作用域限定,那么指定constvar又有什么意义呢? - Coderer
8
在当前的实现中,这将有效,因为constvar具有相同的范围,即函数级别而不是块级别。但是,如果按照即将推出的ECMAScript标准来实现,constlet具有相同的范围,这意味着它将不起作用。 - Jasper
4
@Coderer 使用了错误的语言。在 JavaScript 中,变量的作用域是函数级别的,这与 C 语言不同。 - doug65536
@Jasper 很不幸。我对他们实际上打破所有使用const的现有代码表示怀疑。 - doug65536
1
说实话,为什么我们没有 const varconst let ... - cwharris
显示剩余2条评论
33个回答

1037
自从ES2015以来,JavaScript引入了const的概念:
const MY_CONSTANT = "some-value";

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

您可以使用var与类似ALL_CAPS的约定,以显示某些值不应被修改,如果您需要支持旧版浏览器或使用遗留代码:

var MY_CONSTANT = "some-value";

93
请注意,如果您不需要跨浏览器兼容性(或者您正在使用Rhino或Node.js进行服务器端编程),则可以使用“const”关键字。它目前受到除IE外的所有现代浏览器的支持。 - Husky
17
现在(3.5年后),你可以使用 Object.defineProperty 来创建既是只读属性又不能被删除的属性。这在所有主要浏览器的最新版本中都有效(但在IE8中有异常,详见@NotAName的回答)。 - Phrogz
33
由于此答案在2015年仍高居谷歌排名前列,因此有必要指出它现已过时。 const 关键字现已正式成为该语言的一部分,并得到了所有浏览器的支持。根据 statcounter.com 的数据,只有少数几个百分点的互联网用户使用不支持 const 的旧版浏览器。 - twhb

317

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

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()方法 :(。

如果不需要严格保护变量的值,那么只需按建议使用全大写的约定即可。


83
总的来说,在JavaScript中你不能强制常量(没有const关键字的情况下)。你可以做的几乎唯一的事情就是限制可见性。需要翻译的内容是:CONFIG.get = someNewFunctionThatBreaksTheCode - Thomas Eding
28
我认为private是JavaScript中的未来保留字,如果我是你就不会使用它。 - Zaq

123

const关键字在ECMAScript 6草案中出现,但截至2015年8月8日,只有少数浏览器支持它。请参考此ES6兼容性表以了解当前状态。语法如下:

const CONSTANT_NAME = 0;

13
若你试图给一个const赋值,它不会抛出任何错误。赋值操作只是失败了,常量仍然保持原来的值。在我看来,这是一个主要的设计缺陷,但只要有一个清晰、一致的命名约定(比如流行的全大写),我认为它不会带来太多麻烦。 - Tyler

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


2
应该提到这仅适用于IE9+ http://kangax.github.io/compat-table/es5/。 - chrisco512
"use strict"; 是什么作用? - Cadoiz
1
@Cadoiz https://dev59.com/ynM_5IYBdhLWcg3wiDuA@Cadoiz 在 JavaScript 中,'use strict' 是什么意思?这个规定背后的原因是什么? - Unmitigated

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>

53
男孩,说点与跨浏览器无关的事情吧……但还是要给你点赞,因为你有些不拘一格的思考方式。 - Tom
14
VBScript是什么? ;) (翻译:VBScript是一种脚本语言,常用于Windows操作系统中的自动化任务和网页开发。原文中的笑脸表情意味着对VBScript的提问可能是带有玩笑或嘲讽意味的。) - tybro0103
2
通常我会对一些与跨浏览器相关的问题进行投反对票,尤其是那些只提供IE特定答案的问题。因为我讨厌那些认为IE的JavaScript实现是“唯一”的人,而其他浏览器则可以被忽略。顺便问一句,还有谁在使用IE以外的浏览器呢? - Ant
@Cooluhuru,这个脚本似乎处理了IE浏览器(使用VBScript)和非IE浏览器(使用JavaScript const)。你能解释一下它有什么问题吗? - Andrew Grimm
我仍然很难接受常量可以被改变。 - Norbert Norbertson

59

1
值得注意的是,这不像传统的常量。这只允许您定义一个常量属性(非常量对象)。此外,它不会生成错误,甚至返回您尝试设置的值。它只是不写入该值。 - Cory Gross
3
最近我读到一篇文章,称在 ECMAScript 5 的严格模式下,对 writable: false 的属性进行赋值实际上会抛出错误。这是写入 'use strict' 到你的代码中的另一个原因。 - Cory Gross
7
实际上,你可以省略 writable: false,因为这是默认值 - sam

24

不,一般而言不支持。Firefox 实现了 const,但我知道 IE 不支持。


@John 指出了一个常见的 const 命名惯例,在其他语言中已经使用了多年,我认为你完全可以采用这种方式。当然,这并不意味着某个人不会覆盖变量的值。 :)


11
众所周知,如果IE没有实现,那么它就跟不存在一样。 - Josh Hinman
3
不幸而实际上,这是真的。IE确实拥有巨大的市场份额。如果我经营一家企业并使用内部网络应用程序,我会将标准化浏览器选择为Firefox。我不知道为什么那么多人关心IE,它很糟糕。 - Jason Bunting
@Rich:谁说我的观点是事实了?你做出了相当大的假设。此外,就我而言,IE很糟糕这一事实是不争的事实。你可以有自己的事实,我并没有说你必须相信我的。:P 吃颗安定或者什么的吧... - Jason Bunting
@Rich B,是的,那只是一个愚蠢的评论,相信我,我知道,我常常发表很多愚蠢的评论。@Jason B. - 有趣的是,昨晚我遇到了这个问题.. const在FF中有效但在IE中无效。感谢您的澄清。 - theman_on_vista
谁在乎IE?我不在乎!FF或Chrome或Opera等几乎可以安装在每个操作系统平台上。此外,计算机零售商通常知道旧版IE很糟糕,因此他们经常(甚至每次)在销售计算机之前安装替代浏览器。因此,我已经决定对于不兼容的浏览器完全不关心:如果浏览器开发人员关心遵守标准,他们的产品可以使用我的应用程序,如果不遵守,用户将使用其他浏览器...我可以接受;-) 但是微软能承受失去市场份额吗?不能,所以“他们”将改变他们的开发策略! - willy wonka

20

Mozilla的MDN Web文档提供了有关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、const、Map、Set和WeakMap,以及__proto__以改进互操作性。


26
“它从未在所有浏览器上可用过。”如果您不在IE中使其可用,则永远不会在所有浏览器中出现。 - km1
推动标准化并不适合每个人 ;) - 公司来了又走 - 感谢您引用了这个木头中的可能性。 - Quicker
再说一句:VBA在所有浏览器中都不是一个共识特性,而且微软支持VBA中的const - 这就是引导开发预算的精髓 ;) - Quicker

20

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

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


alert(MY_CONSTANT());

6
值得指出的是,这与@Burkes回答(@trinithis的评论中提到的)所涉及的相同问题有关。MY_CONSTANT = function() { return "some-other-value"; } 这段代码会导致问题。不过总体而言,这是个不错且快速的解决方案,点赞。 - Patrick M
14
这种写法与 var SOME_NAME = value 没有任何优势(仍然是可变的),需要更多代码,并需要解释。 - mikemaccana
@PatrickM 虽然你可以修改这种伪常量,但在其他语言(例如 C)中,你本不应该能够修改常量,但你仍然可以通过指针等方式来实现。因此,只要你使用一些至少 暗示 它是一个常量的方法,我认为就可以了。 - rev

17

使用“新”Object API,您可以像这样做:

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

请看这个链接,了解更多具体信息。它不是一级变量,因为它附加在对象上,但如果有作用域,任何东西都可以附加到其中。this同样有效。

例如,在全局范围内执行此操作将在窗口上声明伪常量值(这是一个非常糟糕的想法,您不应该轻率地声明全局变量)。

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

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

注意:赋值操作会在控制台中返回被赋的值,但变量的实际值并未改变。


在Safari中无法工作,如果您在Mozilla中再次执行定义语句并使用不同的值,则会重新分配该值。 - Akshay
2
不是“在Safari中无法工作”,而是“在Safari中不支持”。这不是同一回事。如果你尝试这样做,它应该会抛出一个“Uncaught TypeError: Cannot redefine property: <property name here>”的错误。要么你做错了,要么你的Firefox实现有问题。我猜两者都有点。 - tenshou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接