WEB开发网
开发学院网页设计JavaScript javascript必知必会之closure 阅读

javascript必知必会之closure

 2009-09-21 00:00:00 来源:WEB开发网   
核心提示: 关于closure的效率 因为在closure的实际应用可能会多次去生成一个内部函数(匿名),所以存在可能的效率问题.(对象的建立,内存管理释放等).所以,应该尽量减少内部函数的生成, 而使用函数的引用.例如://关于效率的例子flag=false;//这样,每次调用Outer时会产生匿名函数的

关于closure的效率

因为在closure的实际应用可能会多次去生成一个内部函数(匿名),所以存在可能的效率问题.(对象的建立,内存管理释放等).

所以,应该尽量减少内部函数的生成, 而使用函数的引用.

例如:

// 关于效率的例子
flag = false;
// 这样,每次调用Outer时会产生匿名函数的开销
function Outer(obj)
{
obj.fun = function(){
alert("I am " + this.name);
};
}
if (flag)
{
var obj = { name : "zhutao"};
Outer(obj);
obj.fun();
}
// 更好的处理方式
function Outer_better(obj)
{
obj.fun = showme;   // 这样调用的只是函数的引用
}
function showme()
{
alert("I am " + this.name);
}
if (flag)
{
var obj2 = { name : "zhutao"};
Outer_better(obj2);
obj2.fun();
}

应用建议

Don't use closures unless you
really need closure semantics.
In most cases, nonnested
functions are the right way to go.
Eric Lippert, Microsoft

上面的论述是基于效率的考虑, 而 IE 4-6 在使用closure时可能会存在内存泄露的问题,参考 JavaScript Closures 中的相关部分.

而在某些场合,你可能必须要使用closure, 如 循环问题.

代码:

flag = true;
// 向body中生成一些链接,然后绑定事件
function addLink(num)
{
for(var i=0; i<num; i++)
{
var link = document.createElement('a');
link.innerHTML = "Link " + i;
link.onclick = function(){
alert(i);
};
document.body.appendChild(link);
}
}   //可惜的是,当你点击每个链接时,输出的都是 Link 4
// 使用closure 可以解决这个问题
function addLink2(num)
{
for(var i=0; i<num; i++)
{
var link = document.createElement('a');
link.innerHTML = "Link" + i;
link.onclick = function(j){ //使用closure
return function(){
alert(j);
};//返回一个函数
}(i);//调用这个函数
document.body.appendChild(link);
}
}
window.onload = addLink(4);
window.onload = addLink2(4);

为什么会出现上面的这个问题?(事实在之前的的一个项目中,也遇到了相同的问题,但是当时还不懂closure, 也是一头雾水)

这是因为,对于addLink, 在退出addLink函数之前, i已经变成了4,所以无论后面的事件触发,输出的都是4.

但是后者,使用了closure.使得j引用了当前的循环中的i,所以对于每个后续触发事件,都会按照预期地得到相应的结果.

这即是一个典型的closure应用场景, 而如果不使用, 就无法解决这个问题.

结论

下面这段摘抄自 Summary of JavaScript closures :

当你在一个函数中使用另一个函数时, 会产生一个closure

当你使用eval()时, 会产生一个closure.

最好认为closure总是在函数入口处产生,并且本地变量自动添加到closure中

其它的细节可参考上面的链接.

总之, 关于closure,你必须记住以下几点:

closure就是提供了一种变量共享的机制(内部函数可以访问外部函数的变量)

注意closure可能引用的效率问题(如何避免,参见文中详述)

具体的应用场景要熟悉

上篇博文讲的是 prototype, 下篇博文预计会讲 this关键字, 欢迎大家讨论和留言.

编缉推荐阅读以下文章

  • javascript必知必会之prototype

上一页  1 2 3 4 

Tags:javascript closure

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接