前几天我在 Twitter 上谈到了 JavaScript 中的 const。Kyle Simpson 指出我以前分享的一篇文章中有关于 const 的一个误解。但个人想法是,至少我能理解这种糊涂来自哪里,由于 const 与我预想的工做方式不太同样(注,我并非说 const 是错的,只是说它与个人预想有差异。)javascript
虽然我跟 Kyle Simpson 对话很短,可是这段对话仍然涉及到了许多词汇和概念。所以我以为本身不妨深刻研究一下,从而使本身不只更加理解常量的概念,并且更加了解用 const 声明的变量在 JavaScript 中究竟是如何工做的。html
须要指出的是,Kyle Simpson 的确写过一篇关于此主题的帖子,可是这篇博客已经下线了。并且他的确经过 Wayback Machine 分享过一个版本。这篇博客值得一读,由于他写得很深刻: https://web.archive.org/web/20151113135159/http:/blog.getify.com/constantly-confusing-const前端
什么是常量若是你在谷歌搜“什么是编程中所谓的常量?”,你会发现许多页面将常量定义为维基百科中定义的那样,即“在正常执行中没法被程序改变的值。”java
表面上看,这彷佛很简单,就是设置一个值,一个没法改变的值。这对于可读性和错误检查会十分有用。可是,并不是全部语言都有常量,并且拥有常量的各个语言处理常量的方式也不太同样。例如,在一些语言中,常量所表明的值的类型是有限的。程序员
一旦你走出简单的值类型范围后,事情就会变得使人糊涂了。这一点很重要,这也是我对 JavaScript 中的常量感到糊涂的起点。这里,我会举一个例子,而不是解释。如今,假设我要像这样设置一个常量:web
const NAME = "Brian";
彷佛很明显的是,给 NAME 指定任何新的值都会出现错误。可是,若是我像下面这样作呢:编程
const ME = {name:'Brian'};
若是我改变 ME.name 的值,是否还会出错?有人会说本质上我并无改变 ME 的值,由于它仍然指向一样的对象,即便这个对象已经被改变了。但要说明的是,在 JavaScript 中,这并不会出错。微信
JavaScript 中的常量在这里,会出现计算机科学家们熟悉的概念,那就是基元和不变性。咱们会谈一点这方面的内容,但为了不让本文成为一本计算机科学书籍,我不会深刻地探讨这两个概念。ide
简单来讲,不可改变的对象是指一个建立后便没法改变其状态的对象。而 JavaScript 中的基元是指“一个不是对象但没有方法的数据。” (来源:MDN)函数
JavaScript ES6(又称 ES2015) 中加入了 const 关键词。以前,一般的约定是使用一个标准的变量,但它必须以全大写命名,如 MY_CONSTANT。但这并无真正规定一个变量是否可以被更改,它只是对程序员的一个提示,提示他们不要更改该变量。
用 const 声明的 JavaScript 常量能够是全局范围的,也能够是区块范围的。若是常量位于区块内(即在{ 和}之间),它们就自动是区块范围的。若是它们没有在区块内,则它们是全局范围的。可是,与用 var 声明的变量不一样的是,它们不会成为 window 对象的特性。若是它们位于模块中,位于区块外用 const 声明的变量对于该模块而言将是全局范围的。
const 和 var 另外一个有趣的区别在于,它们提高 (hoist) 的方式不一样。当你用 const 或 let 声明一个变量时,该声明将被提高,可是它的初始化值并非 undefined,所以若是你尝试在声明前访问它的话,会出现引用错误。正以下面所示,第一个 console.log 引用了以 var 定义的变量,它的返回值为 undefined。而第二个 console.log 引用了以 const 定义的变量,却出现了一个错误。
这一现象被称之为暂时性死区,这个名字使它听起来比实际上更加不吉利。
如前所述,最后一条关于 JavaScript const 重要的一点是:const 声明为一个值建立了一个只读的引用。这并非说其表明的值是不可改变的,而只是说变量标识符不能被从新指定罢了。来源: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
这也是关于 const 的困惑再次出现的地方。当你将 const 用于 JavaScript 基元类型(如布尔值、数字、字符串等)时,const 的行为与你预想的一致(任何从新指定值的尝试都会致使错误)。可是,当你将 const 用于 JavaScript 对象时(包括数列、函数等),这个对象仍然是能够更改的,也就是说,这个对象的特性仍然能够被更改。
想要了解 let 和 const 做用域的详情,请阅读 Axel Rauschmayer 的 “为没耐心的程序员设计的 JavaScript”这篇文章: https://exploringjs.com/impatient-js/ch_variables-assignment.html
若是你想参与更多前端技术交流,获取更多专家分享,能够加入咱们的“前端技术交流群“,社群内会常常讨论前端相关的技术、分享免费学习资料,咱们也会邀请前端专家进行社群分享、直播、公开课等活动。 若是你感兴趣,欢迎添加社群管理员微信GeekUni004,回复“前端群”申请入群。你应该用 Const 吗?
回答这个问题有点难,特别是由于 let 拥有一样的区块做用域和提高优点(我将后者描述为一个潜在的优点,由于若是你在声明某个变量前不当心访问了某个变量的话,你提高 var 的方式可能会致使出现不太常见的错误)。鼓吹 const 优点的人一般关注于代码的可读性。经过使用 const,你至关于代表了这个特定的变量不该该被更改,而且在某种程度上,你强调了这一点。然而,人们好像常常对此产生误解这一事实把支持 const 可读性的观点给削弱了,就像本文开头所讲的那样。这的确可以必定程度上防止他人从新指定这个变量的值,可是我想引用一下 Kyle 的话:
事实上,许多程序员都认可,这一保护可以避免一些不知情的程序员意外地改变某个 const。然而,有个例外,我认为在现实中极可能发生的状况是,当一个程序员须要更改某个变量但却得到了一个“const- 抛出”错误时,他可能会将 const 直接修改为 let,而后继续工做。
因此,若是 const 提供的保护较为有限的话,那么咱们可能只须要在意风格偏好了,特别是在 let 和 const 之间作选择时。但若是你的变量须要表明一个基元值,并且这个基元值并不会改变,那么很显然,使用 const 是个合理的选择。可是,请注意,若是该值并不是一个基元值,那么从可读性的角度来说,使用 const 会给人带来更多困惑,而不是帮助。
英文原文:https://remotesynthesis.com/blog/javascript-const