zoukankan      html  css  js  c++  java
  • 关于在for循环中绑定事件打印变量i是最后一次。

    其实函数引用的外部变量都是最后一次的值。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            #box{
                100px;
                height:100px;
                background-color:pink;
            }
        </style>
        <script src="index.js"></script>
    </head>
    <body>
        <div id="box"></div>
    </body>
    </html>
    ///////////////////////////////js代码//////////////////////////
    window.onload = function(){
        var box = document.getElementById("box");
        var num = 0;
        function a(){
            console.log(num);
        }
    
        box.onclick = function(){
            num ++;
            a(); // 1,2,3,4....每次单击都会加1,说明函数引用外部变量是引用那个变量的最后一次的值。
        }
    }

    再来看一个例子:

    window.onload = function(){
        var box = document.getElementById("box");
        var num = 0;
        for(var i=0;i<10;i++){
            box.onclick = function(){
                console.log(i); //总是打印10
            }
        }
        
    }

      如果你知道作用域链就好办多了,在这个函数里面的i其实引用的是最后一次i的值,为什么不是1,2,3,4...呢?因为在你for循环的时候,你并没有执行这个函数,你这个函数是在你点击的时候才执行的,当执行这个函数的时候,它发现它自己没有这个变量i,于是向它的作用域链中查找这个变量i,因为当你单击这个box的时候已经for循环完了,所以储存在作用域链里面的i的值就是10,最后就打印出来10了。

    for(var i=0;i<10;i++){
        function a(){
            console.log(i);
        }
        a(); //1,2,3,4,5....
    }

    为什么这样就可以呢?因为你在循环变量i的时候已经执行了函数a,自然变量i是什么就打印出来什么。

    现在知道为什么绑定事件的时候打印出来的是最后一次的for循环的值了吧。

    如果你知道理解这段话,我相信你知道怎么去解决这个问题。

      解决方法1:让这个函数直接执行。

      解决方法2:将每次for循环中的变量i保存到某个地方。

    方法1:

    window.onload = function(){
        var box = document.getElementById("box");
        var num = 0;
        for(var i=0;i<10;i++){
            box.onclick = a();
            function a(){
                console.log(i); //1,2,3,4.....
            }
        }
        
    }

      虽然这样可以打印出每次的变量i的值,但是我们没有点击box的时候它已经执行完了,直接无视了点击事件,也就是说这个点击事件已经可有可无了,所以我们用这种方法在绑定事件中就显得不那么可用了,那我们用方法2试试吧。

    方法2:

    window.onload = function(){
        var div = document.getElementsByTagName("div");
        var num = 0;
        for(var i=0;i<div.length;i++){
            (function(i){
                div[i].onclick = function(){
                    console.log(i); 
                }
            })(i)
        }
        
    }

      成功打印每个i的值,原理就是通过自执行函数,并且将变量i保存到这个自执行函数的参数中。如果你不知道什么是自执行函数可以看初识js中的闭包这一节。

    你们我们应该选择那种方法呢?当然看你的情况了,如果没有关于绑定事件的话,就是说让这个函数直接执行的,那就用方法1,否则用方法2,另外方法2通用,但是因为里面的i会一直保存到内存中比较消耗性能的原因,所以在没有必要的情况下尽量不要用这种方式,其实还可以将i绑定到元素的属性上。

  • 相关阅读:
    最大子数组求和并进行条件组合覆盖测试
    Ubuntu 16.04 c++ Google框架单元测试
    The directory '/home/stone/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If execu
    Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info -a -e /usr/bin/appstreamcli; then appstreamcli refresh > /dev/null; fi'
    个人博客作业三:微软小娜APP的案例分析
    补交 作业一
    补交 作业二:个人博客作业内容:需求分析
    嵌入式软件设计第12次实验报告
    嵌入式软件设计第11次实验报告
    嵌入式软件设计第10次实验报告
  • 原文地址:https://www.cnblogs.com/pssp/p/5215417.html
Copyright © 2011-2022 走看看