• 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在作为内层循环的参数,其思想应该是一样的.

  • 相关阅读:
    Auto X2021 K Increasing Sequence
    拉普拉斯平滑处理 Laplace Smoothing
    博学之
    Python-生成音乐-pyshnth
    Python-Kivy ImportError: DLL load failed: 找不到指定的模块
    Python-Word模板填充-docxtpl
    Python-文字转语音-pyttsx3
    Virtual Box中Ubuntu使用"桥接网卡"不能联网而使用"网络地址转换(NAT)"却可以上网
    STM32的HAL库中的DMA_FLAG_TCIF3_7等几个宏定义的含义
    Linux下编写互相通信的驱动模块并将其加入到内核中
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13317766.html
Copyright © 2020-2023  润新知