likes
comments
collection
share

【JS】谈谈var、let的区别

作者站长头像
站长
· 阅读数 3

前言

学习JavaScript的小伙伴是否有过被 var 和 let 弄得很疑惑的时候呢?如果有,请认真看完本文,一定会对你有很大的帮助。

正文

var let 是 JavaScript 中用于声明变量的两种关键字,它们之间有一些区别。

  1. var

    • var 是在 ES5 中引入的变量声明关键字。
    • 它具有函数作用域,而不是块作用域。这意味着当你使用 var 声明变量时,它会提升到最接近的函数作用域的顶部。
    • 如果在同一个作用域内使用 var 多次声明同名变量,后面的声明会覆盖前面的声明。
    • var 声明的变量可以在声明之前被访问(变量提升)。
  2. let

    • let 是在 ES6 中引入的块级作用域变量声明关键字。
    • 它具有块级作用域,意味着它的作用域限制在它所在的块(大括号 {})内部。
    • 使用 let 声明的变量不会像 var 那样被提升。这意味着你不能在声明之前访问使用 let 声明的变量。
    • 同一个块作用域内不能使用 let 声明同名变量,否则会报错。

这样看大家可能还不是很懂,我用几段代码让大家加深理解:

例如声明的提升,对于var声明的变量,具有声明提升的特性

    a = 2
    var a 
    console.log(a) //2

可能你会说变量a的声明不是在a = 2之后吗?那么这就是声明提升的奥妙之处了!简单来说,当你使用 var 声明变量时,它会提升到最接近的作用域的顶部。

但是可能有的人就会问了:


    var a 
    console.log(a) //undefined
    a = 2

为什么这里是undefined的呢?那么我告诉你,提升只对变量和函数的声明有用,但是对变量的赋值操作或者函数的调用操作来说,没有提升这一回事。 所以console.log(a)的执行顺序先于a = 2,所以输出undefined。

那么对于es6新增的let关键字就更有意思:

    a = 2 //ReferenceError
    let a
    console.log(a); 

很明显,let声明的变量也不存在提升,所以我们必须按照写C语言那般,严格按照代码执行顺序书写。它具有块级作用域,意味着它的作用域限制在它所在的块,这一点可以让let在某些var难以解决的问题上产生奇效。

实战

大家可以想想下面的代码:

for(var i =0;i<5 ; i++){
    setTimeout(() => {
        console.log(i);
    },500)
}

这段代码的初衷是输出0、1、2、3、4,且时间间隔是500ms,但是结果大跌眼镜,是五个5。这究竟是为什么呢?

在这个例子中,使用 var 关键字声明的变量 i 具有函数作用域,而不是块级作用域,在这里i是属于全局的。在 JavaScript 中,setTimeout 回调函数是在循环完成后才执行的,因此当回调函数执行时,i 的值已经是循环结束后的值,即 5

解决方案:

for (var i = 0; i < 5; i++) {
    (function (j) {
        setTimeout(() => {
            console.log(j);
        }, 500);
    })(i);
}

这里有几个点需要注意,( function(){....} )() 是立即执行函数,即每循环一次调用一次,再去通过传参的方式将i传入闭包函数内部的作用域,以保证每轮循环迭代能够将i保存下来,这样,每个回调函数将会捕获到循环迭代时 i 的值,而不是最终的 5

2. 现在可以请我们的let登场了:

for(let i =0;i<5 ; i++){
    setTimeout(() => {
        console.log(i);
    },500)
}

没错,把var改成let即可,就这么简单。使用 let 关键字声明的变量 i 具有块级作用域,每次迭代循环都会创建一个新的 i,而不是共享同一个 i,并且每个 i 的作用域都是在当前循环迭代中。 因此,每个 setTimeout 回调函数捕获到的 i 都是当前迭代中的值,而不是循环结束后的值。

最后

希望大家不用再对 var 和 let 疑惑了,弄清楚varlet对今后JS的学习都会有很大的帮助。

后期我还会更新let的详解,有兴趣的小伙伴记得点赞和关注我哦!

如果你也在准备春招,欢迎加我微信lyhGetup,一起交流,一起刷面经。