let/const 和var的区别
想必涉及let/const 最多的问题就是 和 var的区别了,一般的解答是这样的:
- let/const 声明的变量的作用域是块级的,var 声明的变量的作用域是全局的;
- let/const 不能重复声明已存在的变量,var 可以重复声明已存在的变量;
- var 不能限制对变量的修改,const 声明的变量不能修改;
- let/const 有暂时死区,不能提升。
特殊情况
for(var i=0; i<10;i++){
setTimeout(function(){
console.log(i)
}, 0)
}
// 打印结果为 10个 10,原因都知道,就不多解释了
但是 将 var 改为let 后,结果就不一样了
for(let i=0; i<10;i++){
setTimeout(function(){
console.log(i)
}, 0)
}
// 打印结果: 0 1 2 3 4 5 6 7 8 9
这是为什么呢?
for 循环头部的 let 不仅将 i 绑定到了 for 循环的块中,事实上它将其重新绑定到了循环 的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。
可以这样理解:
for(var i=0; i<10;i++){
let j= i;
setTimeout(function(){
console.log(j)
}, 0)
}
// 打印结果: 0 1 2 3 4 5 6 7 8 9
关于暂时死区,又是什么原因呢,为什么 var 却没有呢?
{
console.log(x);
let x
}
{
console.log(x);
const x
}
// 这两个都会报一样的错
// Uncaught ReferenceError: Cannot access 'x' before initialization
// x 被初始化之前不能使用
// 但是使用var 声明却不会报错
{
console.log(x);
var x
}
// undefined
报错的内容是 “初始化之前不能使用”,那么这就涉及到了变量的声明过程了:
创建、初始化、赋值
function 声明的「创建、初始化和赋值」过程
fn2()
function fn2(){
console.log(2)
}
- 找到所有用 function 声明的变量,在环境中「创建」这些变量。
- 将这些变量「初始化」并「赋值」为 function(){ console.log(2) }。
- 开始执行代码 fn2()
也就是说 function 声明的代码, 在执行代码之前就已经 【创建、初始化、赋值】了。
var 声明【创建、初始化、赋值】的过程:
- 找到用 var 声明的变量, 在环境中 【创建】这些变量;
- 将这些变量【初始化】 为 undefined;
- 执行代码
- 给变量赋值
let/const 声明【创建、初始化、赋值】的过程:
- 找到let/const 声明的变量,在环境中 【创建】这些变量;
- 执行代码(注意现在还没有初始化,这是最重要的一点);
- 执行 x=1,将 x 【初始化】为1,(注意此处不是赋值,如果是 let x; 则将 x 初始化为 undefined)
- 执行 x =2;对 x 进行【赋值】
这就解释了 为什么在 let x 之前使用 x 会报错:
- console.log(x) 是已经声明了 x ,所以这个 x 就是块内部的 x , 不是外部的 x
- 但是此时只是创建了 x ,还没有初始化,所以不能使用,
关于变量提升的总结:
- let 的「创建」过程被提升了,但是初始化没有提升。
- var 的「创建」和「初始化」都被提升了。
- function 的「创建」「初始化」和「赋值」都被提升了。
let/const 和var的区别
想必涉及let/const 最多的问题就是 和 var的区别了,一般的解答是这样的:
特殊情况
但是 将 var 改为let 后,结果就不一样了
这是为什么呢?
for 循环头部的 let 不仅将 i 绑定到了 for 循环的块中,事实上它将其重新绑定到了循环 的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。
可以这样理解:
关于暂时死区,又是什么原因呢,为什么 var 却没有呢?
报错的内容是 “初始化之前不能使用”,那么这就涉及到了变量的声明过程了:
创建、初始化、赋值
function 声明的「创建、初始化和赋值」过程
也就是说 function 声明的代码, 在执行代码之前就已经 【创建、初始化、赋值】了。
var 声明【创建、初始化、赋值】的过程:
let/const 声明【创建、初始化、赋值】的过程:
这就解释了 为什么在 let x 之前使用 x 会报错:
关于变量提升的总结: