说到 let 和 var 对于前端的同学一定都不陌生,let 是 ES6 提供的一个新的关键字,它和 var 一样都是用来声明变量的,那么你是否想过既生 var 何生 let ?下面就来说一说为什么要加入 let。
首先,在 js 中存在变量提升的问题,所谓的变量提升就是指变量的声明会提升到所有作用域的顶部,比如下面这样:
console.log(a);
var a="123";
上面这段代码经过 js 变量提升处理后就等价于下面这段代码:
var a="1";
var func=function(){
console.log(a);
var a="12345";
}
func();
虽然变量提升给我们带来了很大的方便,但是它会不知不觉的给开发人员带来一些难以察觉的问题,例如下面这段代码:
上面这段代码存在一个问题,在函数中调用的变量 a 并不是 第一行所定义的 a 而是函数内部所定义的 a ,这是因为 js 的变量提升把函数中定义的 a 提升到了函数的开头,要解决这个问题我们就要使用 let 关键字,我们把代码中的 var 全都改为 let 后,再次运行代码,这时控制台就会显示 Identifier ‘a’ has already been declared 这个错误提示。这是因为在函数内部执行 let a 之前 a 位于暂时性死区中,因此这个时候使用变量 a 就会抛出异常。
其次, let 也可以很好的控制变量的作用域范围,我们来看一下下面的代码:
for (var i=0;i<10;i++){
setTimeout(()=>{
console.log(i)
},300);
}
上述代码运行后将会连续输出10次 10 ,这是因为在循环体中 var 变量声明的是一个全局变量,每次循环就是在给这个变量加 1,等到 setTimeout 函数执行回调的时候就这个变量就变成了 10 ,因此会输出 10次 10。同样我们利用 let 来改进一下上面的代码后将会一次输出0、1、2、3、4、5、6、7、8、9,这是因为 let 声明的变量是绑定在块级作用域上的,每次循环就会创建一个新的变量,也就是说每次 setTimeout 执行回调使用的是自己的变量 i 。