• 经典闭包例子详解


    之前花了很多时间看书上对闭包的介绍,也看了很多人的写的关于闭包的博客,然后我就以为自己懂了。

    结果,下午在一个QQ群里,有人问了这道经典的闭包问题,如下图:

    我告诉他去看书上的闭包介绍。告诉他之后,我想我自己要不也写一下,反正花不了多少时间,结果花了好久怎么写也不对..............

    后来看了看书上的,然后自己总结了下,觉得这次应该懂了。下次还不理解我就可以去跳楼了............

    -----------------------------------分割线-----------------------------------分割线--------------------------

    首先我们来了解几个概念:

    立即执行函数:形如 (function(){})();的一类函数;

    闭包:闭包是指有权访问另一函数作用域中的变量的函数。

    作用域链:当代码执行的时候,会创建变量对象的一个作用域链....(具体百度)

    我们再来看这个问题,我重新写了一个,源码如下:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>闭包经典例子详解——huansky</title>
    </head>
    <body>
        <div id="ttt">
            <p >000000000000000000</p>
                <br>
            <p >111111111111111111</p>
            <br>
            <p >222222222222222222</p>
        </div>
    </body>
    <script>
    
        var dom=document.getElementsByTagName("p");
        for(var i=0;i<dom.length;i++){
            dom[i].onclick=function(){    
                console.log(i);//3
            };
        }
        
    </script>
    </html>
    View Code

    首先,代码中的匿名函数没有变量 i,所以它必须向上查找,在全局环境中找到了 i。

    当for循环运行后,全局变量中的 i 变成了3。此时当你点击文字的时候,会调用其绑定的函数,而该函数运行的时候,发现自己没有 i,就会取得全局环境中的 i。

    所以,最后的结果是,不管你点击那段文字,最后结果都是3。

    那怎么办呢?你可以用立即执行函数,看代码:

                for(var i=0;i<dom.length;i++){
                    dom[i].onclick=function(i){
                        return function( ){ 
                        console.log(i);
                        };
                    }(i);
                }         

    我们把参数 i 作为传给立即执行函数,这样,i 的值就传给了立即执行函数的局部变量 i 了。立即执行函数会直接执行,但是其活动不会销毁,因为里面有个匿名函数。执行后局部变量 i 与全局变量 i 联系就切断了,也就是执行的时候,传进去的变量 i 是多少,立即执行函数的局部变量 i  就是多少,并且该局部变量 i 仍然没有消失,因为匿名函数的存在。

    这时候,return中的匿名函数的作用域链中会有两个变量 i。当点击文本的时候,它向上搜索 i 的时候,它找到立即执行函数的局部变量 i ,就停止向上查找了,因此最后的结果就不会是全局变量 i 的值3了。

    有一个方法可以检验你们有没有真的理解上面所说的,看上面的变体,代码:

            for(var i=0;i<dom.length;i++){
                    dom[i].onclick=function(t){
                        return function( ){ 
                        console.log(t);//1
                        console.log(i);//3
                        };
                    }(i);
                }

    其实return中的匿名函数中的 t 就是立即执行函数的局部变量 i,而 i 就是 指全局变量 i,因为立即执行函数中没有变量i,只能继续向上搜索,然后就找到全局变量的 i 了。

    如果看到这里,你还没有理解,有两个原因:一个原因是我表达的不够好,另一个原因是你没有完全理解前面提到的这些概念,还要继续看书。

  • 相关阅读:
    c#中结构与类的区别(转载CSDN.NET)
    初识.net反射技术(转载cnblogs)
    C#利用反射动态调用类成员[转载]
    页面局部无刷新汇总(转载cnblogs)
    范型的用法大全
    Abstract Class 和 Interface用法
    命名的方法 匿名方法 对委托进行实例化
    ApplyStyle 方法
    类型反射的例子(转载)
    out 和 ref 传递数组参数方法
  • 原文地址:https://www.cnblogs.com/huansky/p/5450767.html
Copyright © 2020-2023  润新知