【ES6系列】变量与块级作用域
ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
ES6 的出现已经很久了,由于之前的项目只是基于 ES5 以及之前的版本内容进行开发的,所以没有系统性的梳理学习 ES6 的相关知识。感觉自己已经被发展的车轮落下了好远好远(@﹏@)~,所以在接下来这段时间针对性的进行学习整理,希望能够让自己有所提高,也希望能帮助和我一样的人……
变量
常量 const 命令
常量的定义
在之前的版本 ES5 甚至更早的版本(后面统称 ES5)中,很少能够听到常量的概念,我们也知道,JS 不同于其他的语言,如 Java、C++等,有常量的概念。虽然通过其他的方法能够达到实现常量的方法,但是并不直接、方便。
如可通过下述方式进行常量的实现:
1 |
|
在 ES6 中,定义一个常量则非常简单,通过 const 进行声明即可。
const 声明一个只读的常量。一旦声明,常量的值就不能改变。
1 |
|
const 声明的变量不得改变值,这意味着,const 一旦声明变量,就必须立即初始化,不能留到以后赋值。
const 定义常量的本质
const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const 只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。
如:
1 |
|
let 命令
在 ES6 中新增了 let 命令,可以用来声明一个变量,作用类似于之前常用的 var,但是和 var 声明的变量其有效的作用域不同,let 声明的变量只在 let 命令所在的代码块内有效。
如:
1 |
|
通过上面代码的执行结果来看能够看出,let 声明的变量只在它所在的代码块中有效,即{}所在的代码块内。
那么 let 声明的变量在什么情况下会比较有用呢?先让我们来看下下面一段代码:
1 |
|
可能我们预期的结果是显示 0,2,4,但是从执行代码的结果中能够看出,得到的却是 6,6,6,这是为什么呢?
首先我们上面是使用的 var 声明的一个 i 变量,此处会有一个变量提升,相当于在 for 循环外面声明了 var i = 0 变量。当在 for 循环中时,arrays[i]中的 i 即为每次循环的 i 的值(0,1,2),但是在函数体中并没有将 i 变量取值为每次循环的值,它只是对变量的一个引用,并不是值的引用。当在执行循环中的函数体时,i 变量已经变成了 3,所以每次的结构输出都是 6。这个时候,ES6 中的 let 命令就能够满足我们的要求了。
1 |
|
上面代码中变量 i 只在 for 循环体内有效,只在其所在的块作用域内有效,每次 for 循环时会将 i 变量的值保存在其对应的块作用域中(for 循环的{}),每一轮循环都是重新生成一个新的作用域,在执行 for 循环中声明的函数时,都会获取其对应作用域内的 i 的值。这部分涉及到的作用域相关的概念,我们后面会说到。
1、在前面提到过,var 命令声明的变量会发生变量提升的现象,即变量可以在声明之前使用,值为 undefined。按照一般的逻辑来说,变量应该在声明语句之后才可以使用。所以在 ES6 中为了纠正这个现象,let 命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
2、只要在块级作用域中存在 let 命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
1 |
|
ES6 明确规定,如果区块中存在 let 和 const 命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
3、typeof 不再是一个完全安全的操作。之前我们知道,针对一个没有生命的变量调用 typeof 方法时会返回 undefined,但是在上面出现的“暂时性死区”中,typeof 将会被报错。
使用 let 声明变量时,只要变量在还没有声明完成前使用,就会报错。
4、let 不允许在相同作用域内,重复声明同一个变量。
块级作用域
为什么需要块级作用域
1、内层变量可能会覆盖外层变量
1 |
|
内层的 tmp 变量由于变量提升覆盖了外层的 tmp 变量,导致输出不符合预期
2、计数的循环变量泄露为全局变量
我们上面用到的 for 循环的例子就是这个现象的证明,var 声明的变量 i 在循环结束后泄露成了全局变量。
ES6 的块级作用域
在 ES6 中{}包裹的块即为一个块级作用域,并且块级作用域支持嵌套,如
1 |
|
并且外层作用域不能读取内层作用域的变量;
内层作用域可以定义外层作用域的同名变量。
在之前的版本中,当我们想要实现一个变量只在一个代码块中运行,我们往往需要通过使用立即执行函数来实现。如
1 |
|
但是在 ES6 中则不再必要了,我们可以通过块级作用域就能够实现
1 |
|
本次主要针对 ES6 中的变量和块级作用域进行了梳理学习,并且通过与 ES5 的实现方式进行了对比,从而看出其变化以及快捷与便利。希望能够对您有所帮助,如有写的不对的地方望请指正,从而共同进步。
- 本文作者:冷星
- 本文链接:http://lengxing.club/2018/07/03/%E3%80%90ES6%E7%B3%BB%E5%88%97%E3%80%91%E5%8F%98%E9%87%8F%E4%B8%8E%E5%9D%97%E7%BA%A7%E4%BD%9C%E7%94%A8%E5%9F%9F/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!