javascript 常见的闭包问题的解决办法
2017-04-07 15:51
459 查看
<html> <head> <title></title> <script type="text/javascript"> <!-- function $(elem){ return document.getElementById(elem); } function tag(name,elem) { return (elem||document).getElementsByTagName(name); } function init() { var div=tag("div"); for(var i=0;i<div.length;i++) { div[i].onclick=function() { alert(i); } } } // --> </script> </head> <body> <div id="div" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">0</div> <div id="div1" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">1</div> <div id="div2" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">2</div> <div id="div3" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">3</div> <div id="div4" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">4</div> <div id="div5" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">5</div> <div id="div6" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">6</div> <input type="button" value="click" onclick="init();"> </body> </html>
上段代码本意是在每个div上都加一个事件,即每当点击div时,就显示此div的相应序号。但是运行程序时我们会发现,不论点击那个,只会显示7,这是什么愿因呢。--这就是闭包的问题
原来 在js中,函数中在定义函数,就出现闭包了。此时外层函数中变量是可以在里层函数里利用的,即使外层函数结束。但是当外层中出现循环的时候,如果在里层函数中利用这个循环变量的话,会直接引用这个变量的最终值。
就像上述代码演示的一样。
如何解决呢。
可以利用匿名函数来加以解决。匿名函数会制动执行,我们可以利用这一特性,来产生一个作用域,生命一个变量,来引用外层的循环变量。
如代码所示:
<html> <head> <title></title> <script type="text/javascript"><!-- function $(elem){ return document.getElementById(elem); } function tag(name,elem) { return (elem||document).getElementsByTagName(name); } function init() { var div=tag("div"); for(var i=0;i<div.length;i++){ (function(){ var temp=i; div[temp].onclick=function() { alert(temp); } })() } } // --></script> </head> <body> <div id="div" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">0</div> <div id="div1" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">1</div> <div id="div2" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">2</div> <div id="div3" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">3</div> <div id="div4" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">4</div> <div id="div5" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">5</div> <div id="div6" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">6</div> <input type="button" value="click" onclick="init();"> </body> </html>
由于在内层函数里只要出现循环变量的话 都是最终值,所以我们利用匿名函数 激发出一个作用域,在进入内层循环之前,有另一变量获得该循环变量的值,这一思想是处理闭包问题的精髓。
如下例子:此时并没有明显的for循环,但是 根据上述思想,可以立即加以解决 问题
<html> <head> <title> </title> <script type="text/javascript"><!-- function $(elem){ return document.getElementById(elem); } var id=0; function addDiv() { var text="testtestetsetstsetstst"; var div=$("div"); var divChild=document.createElement("div"); div.appendChild(divChild); divChild.id="div"+id; divChild.innerHTML=" <input type='text' id='row"+id+"'>"+text; divChild.onclick=function() { alert("row"+id); $("row"+id).value=text; } id++; } // --></script> </head> <body> <div id="div" style="height:200px;width:300px"> </div> <input type="button" value="click" onclick="addDiv();"> </body> </html>
解决后代码:
<html> <head> <title> </title> <script type="text/javascript"><!-- function $(elem){ return document.getElementById(elem); } var id=0; function addDiv() { var text="testtestetsetstsetstst"; var div=$("div"); var divChild=document.createElement("div"); div.appendChild(divChild); divChild.id="div"+id; divChild.innerHTML=" <input type='text' style='color:#f00' id='row"+id+"'>"+text; (function(){ var d=id; divChild.onclick=function() { alert("row"+d); $("row"+d).value=text; } })() id++; } // --></script> </head> <body> <div id="div" style="height:200px;width:300px"> </div> <input type="button" value="click" onclick="addDiv();"> </body> </html>
补充:看到有网友这样解决了问题:
<html> <head> <title> </title> <script type="text/javascript"><!-- function $(elem){ return document.getElementById(elem); } var id=0; function addDiv() { var text="testtestetsetstsetstst"; var div=$("div"); var divChild=document.createElement("div"); div.appendChild(divChild); divChild.id="div"+id; divChild.innerHTML=" <input type='text' style='color:#f00' id='row'"+id+">"+text; divChild.onclick=function(f){ return function(){ alert(f); } }(id) id++; } // --></script> </head> <body> <div id="div" style="background:#000;color:#fff;height:200px;width:300px"> </div> <input type="button" value="click" onclick="addDiv();"> </body> </html>
我个人的理解是 在进入内层循环之前 把id赋值给f,f在作为内层循环的参数,其思想应该是一样的.
相关文章推荐
- javascript 常见的闭包问题的解决办法
- javascript 常见的闭包问题的解决办法
- JavaScript的常见兼容问题及相关解决办法chrome IE firefox
- 常见的闭包问题的解决办法
- JavaScript开发之路02(Sencha Touch使用时常见问题及解决办法)
- javascript(js)浮点数字精度问题的一个解决办法。
- DIV+CSS构建网站时常会出现浏览器不兼容的问题,下面整理了一些常见不兼容问题,及解决办法!
- asp + Access 常见的数据库访问失败问题 Microsoft JET Database Engine 错误 '80004005' 解决办法
- 页面常见问题及解决办法
- PHP session常见问题集锦及解决办法总结
- 解决JBX常见问题最权威的办法(来自borland)
- 网通PPPOE常见问题解决办法三
- BizTalk Server 2006使用过程中常见的问题及其解决办法
- 调试asp.net程序遇见的三个常见问题及其解决办法
- SQL Server Express常见问题及解决办法
- asp + Access 常见的数据库访问失败问题 Microsoft JET Database Engine 错误 '80004005' 解决办法
- 网通PPPOE常见问题解决办法二
- 调试asp.net程序遇见的三个常见问题及其解决办法
- asp + Access 常见的数据库访问失败问题 Microsoft JET Database Engine 错误 '80004005' 解决办法
- 网页中一些常见的问题与javascript解决代码