你好,今天大叔想和你唠扯唠扯 ES6 新增的关键字 —— const。在说 const 关键字之前,大叔先和你唠唠大叔自己对 const 的感受 —— JavaScript 尼玛终于可以声明真正的常量啦!大叔为啥会发出这样滴感叹?实在是“天下苦秦久矣”呀~
话说 long long ago,当初大叔从 Java 技术栈转向前端技术栈,首先要搞定的就是 JavaScript。虽然都说 JavaScript 和 Java 语言有很多的地方是相似滴,但你知道直到大叔发现这货不能声明常量时候的感受吗?!那真是欲哭无泪啊~ 一个堂堂滴编程语言,居然尼玛不能声明常量?!也好意思说自己是个编程语言?!
声明常量好吧~ 大叔不吐槽了,还是说正事儿吧。其实,在 ES5 里面也不是不能声明常量,就是有那么一捏捏的别扭。你知道 Object 有个叫做 defineProperty() 的方法吧?它是用来给某个对象定义属性的。在 ES5 里面就可以通过这个方法间接地来声明常量。
比方说,你现在想在全局作用域里面声明一个常量,其实就可以看作是给顶级对象添加一个属性嘛。带入个场景比较好整明白,假设是一个 HTML 页面里面声明一个全局常量,就可以像下面这样整:
Object.defineProperty(window, 'a', { value: 'a', // 设置该属性的值 writable: false // 设置该属性的值不能写 })这段代码的意思就是给 window 对象增加一个名叫 a 的属性。writeable 的作用就是这个属性能不能写,值为 false 就是只能读不能写的意思。所以,这时的属性 a 就只能访问不能修改。不信咱可以试试:
console.log(a)这时打印的结果比较简单,就是 a。接下来咱们再修改一下试试看是啥结果:
a = 'b' console.log(a)打印的结果还是 a,并没有把 a 的值改成 b。
其实,这样的用法已经很接近常量的用法了。但是,可但是,但可是~ 你不觉得别扭吗?!为啥?大叔给你屡屡:
尼玛我现在要声明的是一个常量,你现在用的是定义属性的语法。
这个示例还好,因为是声明全局常量,可以加到 window 这种顶级对象上。要是在一个函数作用域里面咋办,我找不准上下文对象咋办?!
即使就用这个办法能解决这个问题,也确实不能改值。但是,啥提示没有,你不难受吗?!
常量就是常量,属性就是属性。至少从概念上就别尼玛混淆在一起,你说是不是?!
所以,在 ES6 的新特性里面,大叔终于看到希望 —— const。这货才是真正用来定义常量滴!说到常量,大叔得先给你科普一下到底怎么样才算是常量。
所谓常量,简单来说就是不能变化的值。其实,不仅不能值变化,还不能重复赋值,也不能重复声明,这才算是对滴。
那接下来,大叔就给你看看 const 这货能不能做到这一点:
const a = 'a' console.log(a) a = 'b' console.log(a)这段代码不难看出就是使用 const 关键字声明了一个常量,两处打印的结果分别为:
第一处打印的结果是 a
第二处打印的结果是报错,报错的内容是:TypeError: Assignment to constant variable.,大概的意思就是你把常量当变量赋值了。
看到了吧?!这才是常量。不仅不能改变值,而且会进行报错,告诉你改变值这种行为是不对滴。
声明常量的注意事项当然了,ES6 新增了这样的语法,附带的也有一些需要你注意的事儿 —— 就是在声明一个常量的时候,是必须把常量进行初始化的。不能像声明变量一样,声明和初始化可以分成两个步骤完成。比方说像下面这样婶儿做:
const a a = 'a'这段代码运行之后的结果就是给你报个大错,报错的内容是:SyntaxError: Missing initializer in const declaration,大概的意思就是说你在声明常量的时候没给人家初始化。
你看看,整得多明白!钉儿是钉儿,卯儿是卯儿的。
块级作用域再有就是,const 不仅提供一个真正可以声明变量的方式,还提供了块级作用域。啥?你还不知道呢?!那你就去看看大叔写的这篇文章里面关于块级作用域的内容吧。
在这儿呢,大叔想再次重申一下块级作用域的好处 —— 就是会把之前暴露在全局作用域的一些变量全部限制在一个具体的块级作用域里面。比方说像下面这样婶儿的代码:
if (true) { const a = 'a' } console.log(a)这段代码运行后打印的结果是报错,报错的内容是:ReferenceError: f is not defined。也就是说,你在一个块级作用域里面声明一个常量,在这个块级作用域之外是没办法访问到这个常量的。
暂时性死区(TDZ)既然唠到 const 声明的常量是具有块级作用域的,那就不能不说一下暂时性死区的问题了。啥意思呢?就是说使用 const 声明的常量也同样存在暂时性死区的,不信你来看段代码:
if (true) { console.log(a) const a = 'a' }这段代码运行后的结果是报错,报错的内容还是暂时性死区的错误:ReferenceError: Cannot access 'a' before initialization。