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();
}
foo()
把内部函数baz传递给bar,当调用这个内部函数时(fn),它涵盖的foo()内部作用域的闭包就可以观察到了,因为它能够访问啊。
传递函数也可以是间接的。
var fn;
function foo(){
var a = 2;
function baz(){
console.log(a);
}
fn = baz;//将baz分配给全局变量
}
function bar(){
fn(); //这也是闭包
}
foo();
bar(); //2
无论通过何种手段将内部函数传递到所在的词法作用域之外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。
将一个内部函数timer传递给setTimeout(...)。timer具有涵盖wait(...)作用域的闭包,因此还保有对变量message的引用。
wait(...)执行1000毫秒之后,它的内部作用域并不会消失,timer函数依旧保有wait(...)作用域的闭包。
在引擎内部,内置的工具函数setTimeout()持有对一个参数的引用,这个参数也许叫做fn或func。引擎会调用这个函数,在下面例子中就是内部的timer函数,而词法作用域在这个过程中保持完整。
这就是闭包
function wait(message){
setTimeout(function timer(){
console.log(message)
},1000)
}
wait("Hello, closure");
//jQuery理解闭包
function setupBot(name,selector){
$(selector).click(function activator(){
console.log("Activating: " + name)
})
}
setupBot("Closure Bot 1", "#bot_1");
setupBot("Closure Bot 2", "#bot_2");
本质上无论何时何地,如果将(访问它们各自词法作用域的)函数当做第一级的值类型并到处传递,就会看到闭包在这些函数中的应用。
在定时器、事件监听器、Ajax请求、跨窗口通信或者任何异步/同步任务中,只要使用了回调函数,实际上就是在使用闭包!