let,var,const
1.先总结下来let,var, const
- var的特点
- var可以重复声明
- 不存在块级作用域
- 有变量提升机制(声明提前到当前作用域顶部)
- 全局声明可能会无疑覆盖一个已经存在的全局属性
- let
- 禁止重复声明
- 块级标识符
- 有临时死区的概念(Temporal Dead Zone)
- 全局声明不会覆盖一个已经存在的属性,只会发生遮蔽
- const
- 块级标识符
- 声明变量绑定对象的话,那个变量不可以修改指向,但可以修改对象里面的属性
- 有临时死区的概念(Temporal Dead Zone)
- 全局声明不会覆盖一个已经存在的属性,只会发生遮蔽
我们简单的解释下临时死区(Temporal Dead Zone)的概念
javascript引擎在扫描代码的时候,如果发现变量声明,要么将它们提升至作用域的顶部(var),要么将声明放到TDZ中(let,const),访问TDZ中的变量会触发运行时的错误,只有执行完变量声明后,变量才会从TDZ中移除,那个时候才可以正常访问
if(condition){
console.log(typeof value) // 引用错误
let value = 'blue'
}
上面发生了引用错误,因为在扫描时把value放到了TDZ中,还没有执行声明语句是不可以访问的
2.下面我们对比一下循环和全局两个重要的点即可
2.1循环的对比
所以let在每次循环中都会创建一个新变量,并以之前迭代中同名的变量的值将其初始化
2.1.1 我们用let进行的循环
for (let index = 0; index < 3; index++) {
setTimeout(() => {
console.log(index);
}, 1000);
} // 执行完 0,1,2
用babel编译成ES5以后
var _loop = function _loop(index) {
setTimeout(function () {
console.log(index);
}, 1000);
};
for (var index = 0; index < 3; index++) {
_loop(index);
}
2.1.2 我们用var来进行循环
因为在此处我们共享了一个变量index异步代码在index===3 的时候才才开始执行的
for (var index = 0; index < 3; index++) {
setTimeout(() => {
console.log(index);
}, 0);
} // 打印的结果是 3,3,3
改善方法可以用函数表达式 立即执行函数 来改善
for (var index = 0; index < 3; index++) {
(function(num){
setTimeout(() => {
console.log(num);
}, 0);
})(index)
} // 0,1,2
2.1.3 这里我们不可以用const因为会报错修改了常量的值
2.2 全局的区别
2.2.1 var
// 在浏览器中
var RegExp = "hello!"
console.log(window.RegExp); // hello!
console.log(window.RegExp === RegExp); //true
2.2.2 let
let RegExp = "hello!"
console.log(window.RegExp); // ƒ RegExp() { [native code] }
console.log(window.RegExp === RegExp); //false
2.2.3 const
const ncz = 'hi';
console.log(ncz); // hi
console.log(ncz in window); //false