1.简化内部函数代码
当用到内部函数的时候,let会让你的代码更加简洁。
var list = document.getElementById('list');
for (let i = 1; i <= 5; i++) {
let item = document.createElement('li');
item.appendChild(document.createTextNode('Item ' + i));
item.onclick = function(ev) {
console.log('Item ' + i + ' is clicked.');
};
list.appendChild(item);
}
// to achieve the same effect with 'var'
// you have to create a different context
// using a closure to preserve the value
for (var i = 1; i <= 5; i++) {
var item = document.createElement('li');
item.appendChild(document.createTextNode('Item ' + i));
(function(i){
item.onclick = function(ev) {
console.log('Item ' + i + ' is clicked.');
};
})(i);
list.appendChild(item);
}
以上示例的工作原理是因为(匿名)内部函数的五个实例引用了变量i的五个不同实例。注意,==如果你将let替换为var,则它将无法正常工作,因为所有内部函数都将返回相同的i:6的最终值==。此外,我们可以通过将创建新元素的代码移动到每个循环的作用域来保持循环更清晰。
在程序或者函数的顶层,let并不会像var一样在全局对象上创造一个属性,比如:
var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
2.let暂存死区的错误
在相同的函数或块作用域内重新声明同一个变量会引发SyntaxError。
if (x) {
let foo;
let foo; // TypeError thrown.
}
在 ECMAScript 2015 中,let绑定不受变量提升的约束,这意味着let声明不会被提升到当前执行上下文的顶部。在块中的变量初始化之前,引用它将会导致 ReferenceError(而使用 var 声明变量则恰恰相反,该变量的值是 undefined )。该变量处于从块开始到初始化处理的“暂存死区”。
function do_something() {
console.log(bar); // undefined
console.log(foo); // ReferenceError: foo is not defined
var bar = 1;
let foo = 2;
}
在 switch 声明中你可能会遇到这样的错误,因为它只有一个块.
switch (x) {
case 0:
let foo;
break;
case 1:
let foo; // TypeError for redeclaration.
break;
}
但是,重要的是要指出嵌套在case子句内的块将创建一个新的块作用域的词法环境,这不会产生上面显示的重新声明错误。
let x = 1;
switch(x) {
case 0: {
let foo;
break;
}
case 1: {
let foo;
break;
}
}