闭包是由函数所创造的一个词法作用域,里面创建的变量被引用后,可以在这个词法环境之外自由使用,闭包通常用来创建内部变量,使用这些变量不能被外部随意修改使用,同时又可以通过指定的函数接口来操作。闭包使得函数可以继续访问定义时的词法作用域。
最标准的闭包是,通过返回值把可操作定义时的词法作用域函数,返回出来调用像下图:
function foo() {
var a = 2
function bar() {
console.log(a)
}
return bar
}
var baz = foo()
baz() // 2
但是闭包有多种形式,可以通过任何形式的进行索引传递,把操作函数索引返回出来。
function foo() {
var a = 2
function baz() {
console.log(a)
}
bar(baz)
}
function bar(fn) {
fn() // 闭包
}
var fn
function foo(){
var a = 2
function baz() {
console.log(a)
}
fn = baz
}
function bar() {
fn() // 闭包
}
foo()
bar() // 2
本质上 如果将(它们各自词法作用域的)函数当作第一级的值类型并到处传递,就可以理解为闭包,JavaScript 很多使用中都有相关的身影,比如在定时器,事件监听器, Ajax请求,跨窗口通信、Web Workers或其它任何异步中,只要使用了回调函数,实际上就是在使用闭包。
可以总结为,当函数可以记住并访问所在的词法作用域,使函数是在当前词法作用域之外执行,这时就产生了闭包。