首页 > 代码库 > 闭包初窥

闭包初窥

  先扯一段和代码无关的话题。long long ago,我还是个英语很溜的孩子,当然现在也不是很差。学英语的时候,我几乎不听老师的语法讲解,但是我就是不会用错。写代码亦是如此,我不会关心代码为何要这么写,随心所欲。所以我不会去关注闭包实现的原理,只会关心它的用处。so 不要问我闭包为什么这么写,我也不会告诉你什么是闭包。

  闭包到底有什么用?先看一个很经典的例子。

 1 <!DOCTYPE html> 2   <head> 3   </head> 4   <body> 5     <li> 0 </li> 6     <li> 1 </li> 7     <li> 2 </li> 8     <li> 3 </li> 9   </body>10 </html>

  如上代码的基础下写一段js,使得鼠标点击相应的<li>标签,弹出相应的数字。不假思索,几行代码呼之而出。

1 var list = document.getElementsByTagName(‘li‘);2 for(var i=0; i<4; i++) {3   list[i].onclick = function() {4     alert(i);5   };6 }

  代码报错如下:Uncaught TypeError: Cannot set property ‘onclick‘ of undefined 。再一思索,js在dom还没加载前就加载了,需要加上window.onload或者Jq的$(document).ready。修改后的代码如下:

1 window.onload = function() {2   var list = document.getElementsByTagName(‘li‘);3   for(var i=0; i<4; i++) {4     list[i].onclick = function() {5       alert(i);6     };7   }8 };

  but一试,弹出的全是4,与初衷相违背。为什么会这样呢,因为你在鼠标点击标签执行click事件的时候,i早已经循环变成了4!怎么办?你可以污染dom,但是最好的办法是使用闭包。这时闭包的用处就是把变量暂时储存在内存中。修改后如下:

 1 window.onload = function() { 2   var list = document.getElementsByTagName(‘li‘); 3   for(var i=0; i<4; i++) { 4     (function(i) { 5       list[i].onclick = function() { 6         alert(i); 7       }; 8     })(i); 9   }10 };

  至此,大功告成。代码成功地用了一个匿名函数传递并储存了变量。

  该写法其他方面的用处。比如在一个for循环中有定时器,而定时器中要使用循环中的i,这时就可以用闭包把i暂时储存在内存中以便定时器结束后能调用;还有是在循环做ajax的时候,ajax的回调可能要用到循环中的i,这时也可以写成闭包的形式。

 1 for(var i=1; i<=5; i++) { 2   (function (i){ 3     jQuery.ajax ({ 4       type:       ‘GET‘, 5       url:        ‘https://www.xinhehui.com/Financing/Invest/ajaxplist?bid_st=0&time_limit=0&rate=0&start_amount=0&prj_safeguards=0&repay_way=0&guarantor_id=&order=&c=1&p=‘ + i, 6       dataType:   ‘html‘, 7       async:         false,    // 同步,执行完当前ajax才执行下一个,一步步往下执行 8       success:    function (msg) { 9         setTimeout(function() {console.log(i)}, 2000);10       }11     });12   })(i);13 }

 

闭包初窥