变量提升的概念:
使用var声明的变量可以在声明之前被调用,其值为undefined;
console.log(a);
var a=1;
console.log(a);
// undefined
// 1
变量提升只局限于当前的函数,不会提升到函数外面
console.log(a)
// var a = 1;
// console.log(a)
var fn = function () {
console.log(a);
var a=2;
console.log(a)
};
fn()
// ReferenceError: a is not defined
var可以重复声明一个变量只在自己的作用域和子作用域生效,可以理解为一旦在函数中使用var声明变量a,就在函数的顶部先声明了a=undefined,然后再运行到var的时候给a赋值;
函数块中声明的var变量不会影响函数之外的相同名字的的变量
console.log(a)
var a = 1;
console.log(a)
var fn = function () {
console.log(a);
a=3;
console.log(a)
var a=2;
console.log(a)
};
fn()
console.log(a)
// undefined
// 1
// undefined
// 3
// 2
// 1
如果块级作用域中没有定义过该变量,则会去父级作用域去查找该变量;
console.log(a)
var a = 1;
console.log(a)
var fn = function () {
console.log(a);
a=3;
console.log(a)
//var a=2;
console.log(a)
};
fn()
console.log(a)
//undefined
//1
//1
//3
//3
//3
暂时性死区
一旦在函数的作用域中使用了let,const 定义了该变量,就不允许该变量在let或const定义之前被调用,该变量将禁止出现变量提升现象,否则报错
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
// ReferenceError: tmp is not defined
所以let,const更加安全
let定义变量后可以重新赋值,const则不行
总结:
1. 使用var声明的变量可以在声明之前被调用,其值为undefined;(即变量提升)
2.变量提升只局限于当前的函数,不会提升到块级作用域外面
3. var可以重复声明一个变量只在自己的作用域和子作用域生效,同一个作用域多次声明会修改值,多个作用多次声明则不会相互影响
4. 如果当前作用域中没有定义过该变量,则会去父级作用域去查找该变量(这点var和let是一样的)
5.一旦在函数的作用域中使用了let,const 定义了该变量,就不允许该变量在let或const定义之前被调用,该变量将禁止出现变量提升现象,否则报错 (暂时性死区)
经典案例:
for(var i=1;i<=10;i++){
setTimeout(()=>{
console.log(i)
},0)
}
// 10个11
for(let i=1;i<=10;i++){
setTimeout(()=>{
console.log(i)
},0)
}
// 1 2 3 4 5 6 7 8 9 10