闭包(closure)是 ECMAScript 的语法特性,闭包就是在函数内部定义的函数可访问其外部函数的作用域。
作用域(scope)
要理解闭包,首先必须理解JavaScript特殊的作用域。
JavaScript的作用域的特殊之处,就在于函数内部可以访问函数外部的作用域,反之,函数外部却无法访问函数内部的作用域。
var a = 1; // 在函数外部声明变量a
function fn() {
var b = 2; // 在函数内部声明变量b
alert(a);
}
fn(); // 1
alert(b); // undefined
在JavaScript运行函数都会创建属于函数的上下文环境(context)及作用域(scope),作用域即当前环境范围内的变量。
JavaScript最外层的环境为window对象,也就是全局作用域所在的环境。当执行到下一级环境时,下一级环境会主动包含上一级的作用域,最终形成一级一级关联的作用域链(对象的 [Scope] 属性指向该作用域链)。
闭包
就是借助这种作用域链,一方面可使内部函数可访问外部函数的变量;另一方面,闭包还可以抑制外部函数环境的销毁,使其变量始终保存在内存中,直至不需要时再销毁。
示例
function foo(x) {
var tmp = 3;
function bar(y) {
alert(x + y + (++tmp)); // will alert 16
}
bar(10);
}
foo(2); // 16
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + (++tmp)); // will also alert 16
}
}
var bar = foo(2); // bar is now a closure.
bar(10); // 16
一个最简单的闭包例子:
var a = 10;
function test() {
console.log(a); // will output 10
console.log(b); // will output 6
}
var b = 6;
test();
循环绑定事件的例子
var elems=document.getElementsByTagName('li');
for(var i = 0, l = elems.length; i < l; i++) {
elems[i].onclick = function(i) {
return (function(){ // 闭包
alert(i);
});
}(i);
}
注意
由于闭包会使函数中的变量保存在内存中,增大内存开销,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
这篇文章目前没有评论