什么是闭包
闭包:能够引用自由变量的函数就叫做闭包。
那么什么是自由变量呢?这就涉及到词法作用域以及作用域链的知识了。
首先我们来看一个小例子:
function foo() {
var name = "Kobe";
function people() {
console.log(name); // Kobe
}
people();
}
foo();
我们先来看一下代码的执行过程:
1、在 people 函数的函数作用域内查找是否有局部变量 name
2、查找上层作用域,找到了 name 的值是 Kobe,所以结果会打印 Kobe。
我们知道js中有全局作用域,函数作用域以及块级作用域,在函数作用域中,作用域仅局限于函数内部。全局作用域和块作用域里都访问不到它们。而js引擎在执行代码时先会查找当前作用域中是否有name这个变量,如果有那么直接输出,若在当前作用域中找不到就会探出头去,去看上一层作用域(foo函数)中是否有name有没有,如果没有则继续往外探头(全局作用域),若找不到就会返回undifined。像这种作用域套作用域就是作用域链。
接下来说一下词法作用域,在语言的层面来看,作用域其实有两种主要的工作模型:
1、词法作用域:也称为静态作用域。这是最普遍的一种作用域模型,词法作用域在书写的过程中,根据你把它写在哪个位置来决定的。像这样划分出来的作用域,遵循的就是词法作用域模型。
所以完整的代码执行过程应该是:
1、在 people 函数的函数作用域内查找是否有局部变量 name
2、发现没找到,于是根据书写的位置(函数定义的地方),查找上层作用域(全局作用域),找到了 name 的值是 Kobe,所以结果会打印 Kobe。
在我们理解了作用链与词法作用域之后我们再来看什么是自由变量:像people这种嵌套在foo函数内部,它想要查找name变量就得去上层作用域链(foo)中去找,像name这种在函数中被使用,但是又不是函数内部定义的变量,也不是函数参数,而是一个不属于当前作用域的变量,此时name相对于people这个函数来说就是自由变量。
所以我们可以简单地将闭包定义为:引用了自由变量的函数。