也谈逃脱闭包escape closure(for循环中逃脱)

来源:互联网 发布:godaddy域名过户教程 编辑:程序博客网 时间:2024/05/20 17:06

闭包是JS的一个重要特性,它能带给我们程序技巧方面很多的特色,但同时意外的闭包同时也会给我们产生困扰。这篇博文就是记录一下如何逃脱意外闭包。

之前在《精通javascript》里面就看过一个逃脱闭包的例子。最近自己开发的过程也碰到了类似的问题。

将问题抽象一下,首先页面上有3个div元素,要求每个div元素点击的时候弹出提示0,1,2.

<div id='0'>0</div><div id='1'>1</div><div id='2'>2</div>

理所当然的js写法:

window.onload = function(){
  for(var i=0; i < 3; i++){
      document.getElementById(i).addEventListener("click", function(){
        alert(i); })

  }
}

但这个时候点击该页面元素的时候你会发现提示的都是3.

问题在哪里呢?问题就是click绑定的匿名函数形成了闭包。也就是i没有被释放,所以在页面点击的时候总是提示i的最终值:3.

在事件绑定这里我们怎么逃脱闭包呢?也就是我要在这个地方立即返回一个结果函数,而不是调用闭包中的i值。

当然如果你单纯想解决问题,有很多种途径,例如jquery中的data或者给div元素添加expand,采用全局变量,甚至给html中的div元素绑定onclick事件都可以。看过我前面几篇博客的童鞋看到立即返回,可能会联想到立即执行匿名函数,对,这个地方确实可以用它,也是我接下来要讲的解决方案。

首先我们用一个变量在循环开始的地方记录当前循环的i,var idx=i。然后,我们连同绑定事件的句子写在立即执行匿名函数中,然后修改alert(i)为alert(idx),就搞掂了。完整代码:

window.onload = function(){
  for(var i=0; i < 3; i++){
    (function(){
      var idx=i;
      document.getElementById(i).addEventListener("click", function(){
        alert(idx);
      });
    })();
  }
}

这种解决方案,主要就是用一个匿名函数做闭包,存储了i的值为idx,在click绑定的函数调用闭包的idx。JS引擎,在每次循环的时候,立即执行这个匿名函数,并且绑定当前的i。这也是立即执行匿名函数的另一妙用,用闭包逃脱闭包。

原创粉丝点击