【青山学js】js中的作用域(下)

这是我参与更文挑战的第28天,活动详情查看: 更文挑战

块作用域

上面我们说了,在es6之前,js中是没有块作用域的,在es6中,添加了let关键字实现了对块级作用域的支持。那么什么是块级作用域呢,其实就是两个大括号包裹的作用域。而且在我们日常的代码中非常常见,比如if语句后跟的大括号,for循环后跟的大括号。那有的同学会说,这不是有块级作用域吗,那为什么又说没有块级作用域呢?我们又怎么区分有没有块级作用域呢?其实很简单,我们来看看代码就知道了。

if (true) {
    var test = 'hello'
}
console.log(test) // hello
复制代码

看,我们在大括号外也访问到了大括号里面的变量,上面我们说了,在局部作用域(块级作用域也属于局部作用域)外面是访问不到作用域里面的变量的,所以这里的‘块作用域’其实并没有真正的形成作用域,只不过是徒有其表罢了,这样子的危害就是容易污染全局作用域,而且容易给我们造成一定程度上的误解。比如下面这样子。

var index = 5
for (var index = 0; index < 10; index++) {
    /**/
}
console.log(index) // 10
复制代码

很明显,上面代码中for循环中的index污染了全局作用域中的index,如果我们不小心的话很容易造成意想不到的后果,当然我们也可以尽量小心的去给变量命名,细心的检查代码,或者使用try…catch(感兴趣可以去搜一下,或者看js高级程序设计)去实现块作用域,以便代码如我们想象般的运行,可那样就会花费更多的精力,好在es6推出了let关键字,从代码层面支持了块作用域,减少了我们很多的工作量,来看看let的效果

var index = 5
for (let index = 0; index < 10; index++) {
    /**/
}
console.log(index) // 5
复制代码

看,代码完全按照我们想象那样执行,let声明的变量支持块作用域,仅在块作用域内可访问,不会影响全局变量。

下面我们就来看看很经典的一道面试题

for (var index = 0; index < 6; index++) {
    setTimeout(function(){
        console.log(index)
    })
}
复制代码

知道了块作用域再理解这道题就很简单了吧,因为这里用的是var关键字,所以这里没有块作用域,也就是说这里的index其实是一个全局变量,然后每次对index进行++的操作其实都是操作的同一个变量——全局变量index,然后我们里面又用的是setTimeout,一个异步函数,虽然我们这里没有设置定时时间,但它还是一个异步函数,需要等到for循环全部结束后才会运行,这时候index就已经是6了,所以会打印出来6个6。那如果我们把var换成let呢?

for (let index = 0; index < 6; index++) {
    setTimeout(function(){
        console.log(index)
    })
}
复制代码

打印结果:0 1 2 3 4 5

完全符合我们的预期,这里我们使用的是letlet声明的变量支持块作用域,也就是仅在当前作用域内有效,所以这里我们循环中的每一个setTimeout引用的index其实都是单独的变量,互不影响。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享