持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
从ECMAScript6后,我们多了let来申明变量,苦恼也随之而来,那到底该什么时候使用let,什么时候使用var呢?
简单粗暴地理解,var就是全局变量,let是局部变量,真的ok吗?那两个关键字申明的是不同类型的变量吗?关于var的变量提升,let的暂时性死区又该如何理解?
解决以上问题的关键就是明白var和let的本质,它们的根本区别在于声明变量的作用域上,let声明的变量块作用域(块级作用域就是{}),var声明的变量是函数作用域。
let的块作用域
{
let nickname = "小Q"
console.log(nickname); // "小Q"
}
console.log(nickname); // ReferenceError: nickname is not defined
{
var age = 1
console.log(age); // 1
}
console.log(age); // 1
let的作用域是块{},所以块级作用域之外打印nickname就报错了;这里的var申明的变量age是全局变量,所以没有问题。
var的函数作用域
下面我们来理解var的函数作用域:
function test() {
var age = 1; // 局部变量
}
test();
console.log(age) // ReferenceError: age is not defined
var age;
function test() {
age = 1; // 全局变量
}
test();
console.log(age) // 1
var age 在函数test内定义,此时age的作用域限制在test函数内部。调用test时,age被创建赋值;test函数调用结束后,age变量随即被销毁。
实践:for循环实例
下面我们通过for循环中的实例🌰,来加深理解。
for(var i=0; i<5; i++) {
setTimeout(() => console.log(i), 0);
}
// 最后会输出5、5、5、5、5
for(let i=0; i<5; i++) {
setTimeout(() => console.log(i), 0);
}
// 最后会输出0、1、2、3、4
之所以会这样,是因为在第一个for循环中,var申明的迭代变量i,在退出循环后的终值是5,所以再执行定时器逻辑时,输出的都是同一个值5;
而在第二个for循环中,使用let申明迭代变量i后,js引擎会在后台为每次循环申明新的循环变量实例,所以在结束循环后,定时器中引用的都是不同的循环变量实例,输出为0、1、2、3、4;
单调的文字不好理解的话,下面我们还是写代码来解释一下:
// for循环 之let申明循环变量释义:
{
let i = 0;
{
let i = i; // 为每次循环申明新的循环变量实例i
setTimeout(() => {
console.log(i); // 变量实例i的值为0
}, 0);
}
i++;
{
let i = i;
setTimeout(() => {
console.log(i); // 变量实例i的值为1
}, 0);
}
i++;
{
let i = i;
setTimeout(() => {
console.log(i); // 变量实例i的值为2
}, 0);
}
i++;
{
let i = i;
setTimeout(() => {
console.log(i); // 变量实例i的值为3
}, 0);
}
i++;
{
let i = i;
setTimeout(() => {
console.log(i); // 变量实例i的值为4
}, 0);
}
}
看到这,我想你也彻底明白了var和let的本质,那回过头来,我们再来回答下,前面的三个问题:
-
那两个关键字申明的是不同类型的变量吗?
两个关键字申明的并不是不同类型的变量,它们的差别是在变量的作用域上。
-
关于var的变量提升,let的暂时性死区又该如何理解?
所谓的var的变量提升,就是把所有var的声明都提升放到函数作用域的顶部。而let声明的范围是块级作用域,所以不可能检查前面是否已经使用let声明过同名变量,这时在let声明变量前调用let变量就会存在暂时性死区。
-
那到底该什么时候使用let,什么时候使用var呢?
ECMAScript6新增了let,变量有了更明确的申明位置和作用域,尽量不再使用var,哈,这也是红宝书上的建议。
最后
文中若有我没说清楚或错误的地方,欢迎你们评论区留言呀!
反手赞一个吧!对我是莫大的鼓励 💗
参考文献
- [美]马特·弗里斯比:《JavaScript高级程序设计(第4版)》,李松峰译,人民邮电出版社2020年版。