zoukankan      html  css  js  c++  java
  • javascript 常见的闭包问题的解决办法

    <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].οnclick=function() 
    { 
    alert(i); 
    } 
    } 
    } 
    // --> 
    </script> 
    </head> 
    <body> 
    <div id="div" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">0</div> 
    <div id="div1" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">1</div> 
    <div id="div2" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">2</div> 
    <div id="div3" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">3</div> 
    <div id="div4" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">4</div> 
    <div id="div5" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">5</div> 
    <div id="div6" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">6</div> 
    <input type="button" value="click" οnclick="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].οnclick=function() 
    { 
    alert(temp); 
    } 
    
    
    })() 
    
    } 
    } 
    // --></script> 
    </head> 
    <body> 
    <div id="div" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">0</div> 
    <div id="div1" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">1</div> 
    <div id="div2" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">2</div> 
    <div id="div3" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">3</div> 
    <div id="div4" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">4</div> 
    <div id="div5" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">5</div> 
    <div id="div6" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">6</div> 
    <input type="button" value="click" οnclick="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.οnclick=function() 
    { 
    alert("row"+id); 
    $("row"+id).value=text; 
    } 
    id++; 
    } 
    // --></script> 
    </head> 
    <body> 
    <div id="div" style="height:200px;300px"> 
    </div> 
    <input type="button" value="click" οnclick="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.οnclick=function() 
    { 
    
    alert("row"+d); 
    $("row"+d).value=text; 
    
    } 
    
    })() 
    id++; 
    } 
    // --></script> 
    </head> 
    <body> 
    <div id="div" style="height:200px;300px"> 
    </div> 
    <input type="button" value="click" οnclick="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.οnclick=function(f){ 
    return function(){ 
    alert(f); 
    } 
    }(id) 
    
    id++; 
    } 
    // --></script> 
    </head> 
    <body> 
    <div id="div" style="background:#000;color:#fff;height:200px;300px"> 
    </div> 
    <input type="button" value="click" οnclick="addDiv();"> 
    </body> 
    </html> 
    


    我个人的理解是 在进入内层循环之前 把id赋值给f,f在作为内层循环的参数,其思想应该是一样的.

  • 相关阅读:
    mac 鼓捣php 多版本切换
    thinkPHP 导出excel 发布正式环境net::ERR_INVALID_RESPONSE
    js 计时显示 倒着 正者 都行
    LNMP 下 php.ini 文件修改后不生效
    Jquery 遍历数组之$().each方法与$.each()方法介绍
    js 去掉字符串最后一个逗号
    js拼接字符串时,字符串首出现undefined的问题
    PHP 暂停函数 sleep() 与 usleep() 的区别
    在IDEA里创建web项目,以及web 项目部署
    spring容器和springmvc容器,以及web容器的关系
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13317766.html
Copyright © 2011-2022 走看看