zoukankan      html  css  js  c++  java
  • 其实函数引用的外部变量都是最后一次的值。

     

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

    复制代码
    <!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绑定到元素的属性上。

  • 相关阅读:
    Codeforces 1291 Round #616 (Div. 2) B
    总结
    刷新DNS解析缓存+追踪+域名解析命令
    数学--数论--Hdu 5793 A Boring Question (打表+逆元)
    Lucene.net(4.8.0) 学习问题记录六:Lucene 的索引系统和搜索过程分析
    LeetCode 117 Populating Next Right Pointers in Each Node II
    LeetCode 116 Populating Next Right Pointers in Each Node
    test test
    LeetCode 115 Distinct Subsequences
    LeetCode 114. Flatten Binary Tree to Linked List
  • 原文地址:https://www.cnblogs.com/zhangxiaolei521/p/5217901.html
Copyright © 2011-2022 走看看