本文是学习阮一峰《ECMAScript 6 入门》 let 命令部分的笔记。
基本用法
let 命令,用来声明变量,用法类似于 var ,但是所声明的变量,只在 let 命令所在的代码快内有效;
|
|
let命令在for循环中的应用
a. for循环的计数器
|
|
计数器 i 只在 for 循环内有效,在循环外引用就会报错。
b. for循环内声明的变量
|
|
变量 i 是 let 声明的,当前的 i 只在本轮循环中有效,所以每次循环的 i 其实就是一个新的变量。而 JavavScript 引擎内部会记住上一轮循环的值,初始化本轮的变量 i 时,就会在上一轮循环的基础上进行计算,所以最后输出的结果是 6 。
c. for 循环的父作用域和子作用域for 循环有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
|
|
以上代码运行结果输出三次 “abc”, 这表明函数内部的变量 i 与循环变量 i 不在同一个作用域,有各自单独的作用域。
不存在变量提升
“变量提升”: 变量可以在声明之前使用,值为undefined。—— var 命令
let 命令:规定声明的变量一定要在声明后使用,否则报错。
|
|
暂时性死区
在代码块内,使用 let 命令声明变量之前,该变量就是不可用的。这在语法上,称为 “暂时性死区”(temporal dead zone,简称TDZ)。
只要块级作用与内存在 let 命令,它所声明的变量就 “绑定” 在这个区域,不再受外部的影响。
|
|
上面代码中,一开始声明了一个全局变量 tmp,但是块级作用域内 let 又声明了一个局部变量 tmp,导致 tmp 变量绑定在这个块级作用域内。
所以,块级作用域内,在 let 声明变量之前,都属于 tmp 变量的 “暂时性死区”,会报错。
typeof不再百分之百安全
|
|
变量 x 使用 let 命令声明,所以在声明之前,都属于变量 x 的“暂时性死区”,只要用到变量 x 就会报错。而变量 y 没有被声明,使用 typeof 反而不会报错,返回“undefined”。
隐蔽的“暂时性死区”
|
|
第一个函数 test0 中,调用时候报错的原因是:参数 x 默认值等于另外一个参数 y ,而此时 y 还没有声明,属于“死区”。如果 y 的默认值是 x ,就不会报错,因为此时 x 已经声明了。
第二个函数 test1 中,参数 x 的默认值为 2 ,参数 y 的默认值等于参数 x ,而此时 x 已经声明了,所以不会报错。
|
|
ES6规定暂时性死区和 let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明之前就使用这个变量,从而导致意料之外的行为。
暂时性死区的本质: 只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
不允许重复声明
let 不允许在相同的作用域内,重复声明同一个变量。(在函数内不能重复声明参数)
|
|
现在与前面 for 循环的父作用域和子作用域进行对比
|
|
这两个变量 i 虽然是在同一次循环当中,但他们的作用域不同,计数器 i 位于父作用域,而循环体内部的变量 i 位于子作用域,所以这里不会报错。(千万不要以为这也是在同一个作用域内重复声明变量)