概览
背景知识:JavaScript内存管理、JavaScript作用域。
内容
1 闭包定义
闭包:当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。
function foo() {
var a = 2;
function bar() {
console.log(a);
}
return bar;
}
var fn = foo(); // parent函数不会被垃圾回收
fn() // 2
细节:1 bar函数定义在foo函数内部,bar函数本身被当作一个值类型进行传递,并且它在定义的词法作用域之外执行。
2 foo()执行完后不会被垃圾回收,bar()将一直持有对该作用域的引用,而这个引用就是闭包。
以下依然是闭包:
function foo() {
var a = 2;
function baz() {
console.log(a);
}
bar(baz);
}
function bar(fn) {
fn(); // 闭包
}
总结:无论通过何种手段将内部函数传递到所在的词法作用域外,它都会持有对原始定义词法作用域的引用,无论在何处执行这个函数都会使用到闭包。
闭包 定时器:
function wait(message) {
setTimeout(function timer() {
console.log(message);
}, 1000);
}
wait();
分析:wait()执行1000ms后,它不会被垃圾回收,timer()依然wait()作用域的闭包。
闭包 事件监听器:
function addEvent(selector) {
$('selector').click(function cb() {
// todo
})
}
addEvent(btn);
谨记:在定时器、事件监听器、Ajax请求、跨窗口通信、WebWorkers或者任何其他的异步(或同步)任务中,只要使用了回调函数,实际上就是使用闭包。
网友评论