到现在为止,js声明变量的方式有6个了,基础var let const相信大家都已经知道或者使用了,let和const不知道也肯定听说过。今天来说说let和const的特点和与var不同的地方。
1、 ES6新增了let命令,用来声明变量,用法与var一致,但是let声明的变量只在let命令所在的代码块有效。如下图所示。
上面a b输出时a是未定义,b是undefined。说明了let定义的变量只能在let命令的代码块内使用。
2、接下来说let另一个特殊的地方,可以说是解决了历史遗留问题,就是变量提升这个问题。
var命名会发生变量提升的作用,即变量可以在声明之前使用,let命名解决了这个问题。如下图所示。
上面代码中,变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。
3、下面会提到一个专业术语(temporal dead zone,简称 TDZ)
只要块级作用域存在let命名,它说声明的变量就绑定到这个区域,不在受外部的影响。
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
4、let声明的变量不允许再次声明
let不允许在相同的作用域内,重复声明同一个变量。
因此,不能在函数内部重新声明参数。
5、let带来的块级作用域
let实际上为JavaScript新增了块级作用域。
上面函数有两个代码块,都声明了变量n,运行最后输出5。这表示外层代码块不受内层代码块的影响。如果两次都使用var定义变量n,最后的输出的结果会是10;
ES6允许块级作用域的任意嵌套。
{{{{{let insane = 'Hello World'}}}}};
上面代码使用了一个五层的块级作用域。外层作用域无法读取内层作用域的变量。
{{{{ {let insane = 'Hello World'} console.log(insane); // 报错 }}}};
内层作用域可以定义外层作用域的同名变量。
{{{{ let insane = 'Hello World'; {let insane = 'Hello World'} }}}};
块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。
6、const命令
const声明一个只读的常量。一旦声明,常量的值就不能改变。
意味着const函数一旦初始化就必须得立即声明值,不能留到后面赋值。大家可以试试。
其他作用和上面let命令的作用相同,不存在变量提升,也会形成作用域,外部不会影响内部变量。
开头我说过es6有6个声明变量的方法,他们分别是es5中的 var function ,现在es6有了let const class import,后面我会在学习阮一峰老师的es6入门时自己写下一些内容分享。
阮一峰老师的ES6网络书籍地址