在ES2015 中,let可以说是var的进化版本,var在绝大部分情况下可以被let替代。let与var的异同点大致可以用表 3.1 来描述。
表 3.1 let与var的异同点比较let
重复定义检查 可以用下面这段代码来说明。
var可以让同一个变量名在同一个作用域里被定义多次,而这种“特性”很可能会导致一些问题,比如在多人协作开发中,一个变量(如用户信息等数据)是不希望在同一个作用域内被定义两次的。在没有良好的代码审查(Code Review)制度的情况下,ECMAScript在ES2015之前并没有这样的系统级检查能力,而let则加入了这样的功能,当同一个变量名在同一个作用域内被定义第二次时,便会抛出错误,以警示开发者修改代码。
此外,let可被用于 块级作用域 (Block Scope),我们还是以上一小节中的循环绑定事件作为例子。上面的代码之所以出错是因为每一个按钮的事件响应函数中对计数器i的引用所能获取到的数值都是一个不可用的下标,而导致这种情况的原因便是计数器i存在于上一层作用域中。
那么,块级作用域在这里的应用便是,为循环体的每一次执行都产生一个作用域,如图 3.6所示。
图3.6 使用块级作用域后的变量查找
对于原来的代码,只需要改动一个地方即可,将对计数器i的定义从var改成let,便可以在循环体内形成块级作用域,让每一次循环体的执行都能保留当前计数器的数值和引用。
为了更直观地说明在for循环语句中使用var和let的区别,以两段代码来做对比。
就如事件绑定一样,我们通过循环将若干个带有当前计数器i的引用进行对比。而当将这些引用全部读取出来时,可以发现分别使用var和let定义计数器的两个循环语句,所得到结果会截然不同。
使用let形成的块级作用域可以在大部分具有{ ... }的语句中使用,例如for () {},do {} while(),while {} 和 switch() {} 等。