ES6新增了let和const命令,用来声明变量。
let命令
基本用法
let
的用法类似于var
,但是所声明的变量,只在let
命令所在的代码块内有效。
上面代码在代码块之中,分别用let
和var
声明了两个变量。然后在代码块之外调用这两个变量,结果let
声明的变量undefined
,var
声明的变量返回了正确的值。这表明,let
声明的变量只在它所在的代码块有效。
for
循环的计数器,就很合适使用let
命令
不存在变量提升
|
|
上面代码中,变量foo
用var
命令声明,会发生变量提升,即脚本开始运行时,变量foo
已经存在了,但是没有值,所以会输出undefined
。变量bar
用let
命令声明,不会发生变量提升。这表示在声明它之前,变量bar
是不存在的,这时如果用到它,就会抛出一个错误。
暂时性死区
只要块级作用域内存在let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
上面代码中,存在全局变量tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。
ES6
明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错
。
总之,在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ)。
不允许重复声明
let
不允许在相同作用域内,重复声明同一个变量。
块级作用域
ES5
只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
- 内层变量可能会覆盖外层变量
|
|
上面代码中,函数f执行后,输出结果为undefined
,原因在于变量提升,导致内层的tmp
变量覆盖了外层的tmp
变量。
- 用来计数的循环变量泄露为全局变量
|
|
上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。
ES6
中的let
实际上为JavaScript新增了块级作用域。
另外,ES6
也规定,函数本身的作用域,在其所在的块级作用域之内
。
上面代码在ES5中运行,会得到“I am inside!”,但是在ES6中运行,会得到“I am outside!”。这是因为ES5存在函数提升,不管会不会进入 if代码块,函数声明都会提升到当前作用域的顶部,得到执行;而ES6支持块级作用域,不管会不会进入if代码块,其内部声明的函数皆不会影响到作用域的外部。
上面代码中,块级作用域外部,无法调用块级作用域内部定义的函数。如果确实需要调用,就要像下面这样处理。
ES5的严格模式规定,函数只能在顶层作用域和函数内声明,其他情况(比如if代码块、循环代码块)的声明都会报错。
const命令
const这个声明创建了一个常量,可以在全局作用域或者函数内声明常量,在定义常量的同时必须初始化,常量的值不能通过再赋值改变,也不能再次声明
。
文章参考ECMAScript 6 入门