【JavaScript】从作用域角度理解闭包
作用域类型
在 JS 世界中,目前已经有了三种作用域:
● 全局作用域
● 函数作用域
● 块作用域
○ 由let
或者const
声明的变量,如果被一个大括号 {}
这样括住了,那么这个大括号就是一个代码块,大括号括住的这些变量就形成了一个块作用域
一个简单的语句:
var a = 1;
在js引擎中执行上述语句分为两个阶段(一边编译一边运行):
● var a
===》 编译时声明
● a = 1
===》 运行时赋值
在运行时js引擎会找当前作用域下是否有a的声明,没有的话就会往上级作用域查找,一直到最外层全局作用域还没有的话会抛出异常。
作用域链
当一个块或者一个函数嵌套在另一个块或者函数中时,就发生了作用域的嵌套。比如这样:
function addA(a) {
console.log(a + b)
console.log(c) // 报错
}
var b = 1
addA(2) //3
在这个例子中,有两个作用域:addA
的函数作用域和全局作用域。它们的关系示意如下:
在这个查找过程中,层层递进的作用域,就形成了一条作用域链。
闭包
函数使用了既不是函数参数也不是当前作用域的变量就构成了闭包。
const test = (()=> {
let a = 1;
return () => {
return a++;
}
})()
console.log(test(), test())// 1 2
如上面例子,当test
函数内使用a
变量时发现对应函数作用域下并没有,然后沿作用域链往上找,找到对应函数作用域外有然后使用,此时便构成了闭包。