假设:
var m = '变量'
function foo () {
console.log(m)
}
这三行代码中,有一个局部变量m,有一个函数 foo,foo 里面可以访问到m变量,这样的形式就是一个闭包。
用官方一点的话来说:「函数」和「函数内部能访问到的变量」(也叫环境)的总和,就是一个闭包。
复杂一点的:
function foo(){
var local = 1
function bar(){
local++
return local
}
return bar
}
var func = foo()
func()
这里面就有闭包,local 变量和 bar 函数就组成了一个闭包。
为什么要 return bar 呢?
因为如果不 return,你就无法使用这个闭包。把 return bar 改成 window.bar = bar 也是一样的,只要让外面可以访问到这个 bar 函数就行了。
所以 return bar 只是为了 bar 能被使用,也跟闭包无关。
闭包的作用
闭包可以间接访问一个变量,也可以说是“隐藏一个变量”。例如当你定义了一个全局变量a,很容易被赋值为其他值,或者被覆盖,而使用局部变量,其他人又访问不到,因此通过暴露一个函数,让别人间接访问到函数中的局部变量。闭包还可以封装数据和暂存数据。如以下匿名函数:
!function () {
var a = 30;
window.add = function () {
a++;
console.log(a)
}
window.reduce = function () {
a--;
console.log(a)
}
}()
window.add() // 来使a增加 31
window.reduce() // 来使a减少 30
window.a // 无法直接访问到a的值
结果缓存
设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找了,直接返回查找到的值即可。 闭包因为它不会释放外部的引用,从而函数内部的值可以得以保留。