zoukankan      html  css  js  c++  java
  • 用闭包解决 js 循环中函数变量暂存问题

    需求:有一个数组,根据数组的值渲染对应的数字div,单击对应的div 在控制台打印对应的数字。如点击1,控制台打印1.

    问题: 不管点击哪个值 打出来都是4

    代码如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>testFor</title>
    </head>
    <body>
      <div id="container">
      </div>
      <script>
         var arr=[1,2,3,4];
         function clickNum(i) {
             console.log(i)
         }
         for(var i of arr){
             var iDiv=document.createElement('div');
             iDiv.addEventListener('click',function () {
                 clickNum(i)
             });
             iDiv.innerText=i;
             var container=document.getElementById('container');
             container.appendChild(iDiv);
         }
      </script>
    </body>
    </html>

     期望点击会打印出对应的数字,实际打出来的都是4

    原因:

    js函数在声明时,浏览器不会去查看函数内部逻辑。只有函数被使用时 才关心函数内部的变量引用。

    如本例,只有在单击的时候 才会去触发clickNum函数,而此时循环已执行完毕,i已经变成了4。 所以不管哪个div的click 事件打印出来永远都是4。

    解决思路:

    1.因为我们需要用到即时的索引值i.所以 我们需要立即触发此函数。这里需要用到匿名函数。

    2.有了匿名函数立即执行后,我们还需要将匿名函数中的变量暂存起来,留着点击的时候用,这里需要创建一个闭包。因为闭包的本质就是让内部的变量在函数执行完后也不被垃圾回收调。而是暂存起来。所以,如果需要在函数外部拿到函数内部的变量。或者想在将来拿到现在的变量 都只能通过闭包(我个人理解是这样的)

    改后的代码

         for(var i of arr){
             var iDiv=document.createElement('div');
             iDiv.addEventListener('click',function (icopy) {
                 return function () {
                    clickNum(icopy)
                 }
             }(i));
             iDiv.innerText=i;
             var container=document.getElementById('container');
             container.appendChild(iDiv);
         }
  • 相关阅读:
    redis
    配置ssh无密码登陆Linux
    nginx rewrite规则笔记
    git自动部署到服务器
    从电影《Her》来看AI时代下,未来的七夕我们将会如何度过?
    人工智能+智能制造,会产生什么火花?
    大数据时代,市场对企业级云存储的需求更加迫切
    别太神化AI,也别太小看智能医疗
    自动驾驶江湖,将有一场恶战
    区块链 | 详解以太坊的工作原理
  • 原文地址:https://www.cnblogs.com/ada-blog/p/11663091.html
Copyright © 2011-2022 走看看