• 关于闭包的一些知识


    在了解闭包之前先得弄清楚之前讲的作用域的相关知识。

    1、什么是闭包

      可以在外部通过某一种手段(方法)可以访问到内部的变量,这种方法就叫做闭包。

    2、闭包用法的简单举例

      

    function fun1(){
                    var a = 100;
                }
                fun1()
                console.log(a);

      如上代码所示,依我们所学的知识我们此时想要打印出a的值应该不行的,因为a定义的作用域在函数内,全局的GO上是没有a这个变量的,故会报错。

      那么我们怎么样才能让它在外部打印出来呢

                function fun1(){
                    var a = 100;
                    function fun2(){
                        console.log(a);
                    }
                    return fun2;
                }
                
                var fun = fun1();
                fun()

      如上所示,我们先将我们所要执行的代码封装在一个函数内部的另一个函数里,然后返回这整个函数并在外部接受然后触发,这样就能做到我们想要的效果。

      那么,原理是什么呢?

        首先我们分析一下函数的作用域:

          在fun1执行时,生成fun1所对应的作用域,fun1.AO = {a:100,fun2:function}(此处省略分析过程)

          在fun2被返回执行的时候,生成fun2所对应的作用域,fun2.AO = { }

        这时关键点在于,返回出来的fun2这整个函数就算返回到了fun1外面,但是fun2的父级依然还是fun1,那么在fun2的AO中找不到a对应的值,就返回父级的AO中寻找其所对应的值,而fun1的AO中有a,值为100。

        所以这是fun2被返回调用后执行打印出来的结果就是100。

    3、那么我们再看一个情况:

                function fun1(){
                    var a = 100;
                    function fun2(){
                        a ++;
                        console.log(a);
                    }
                    
                    return fun2;
                }
                            var fun = fun1();
                            fun()
                            fun()

      如上所示,根据之前的知识,我们知道这里当fun第一次调用时打印的结果为101,那么当fun第二次调用的时候呢?

      因为fun2的AO中并没有定义a,所以fun2调用时改变的a的值是在其父级也就是fun1的AO中改变a的值,所以当fun第二次被调用的时候,此时fun1中a的值已经变为101,故第二次调用完后打印出来的值为102。

    4、这里我们再讨论一种做法:

            <ul>
                <li>0</li>
                <li>1</li>
                <li>2</li>
                <li>3</li>
                <li>4</li>
                <li>5</li>
                <li>6</li>
                <li>7</li>
                <li>8</li>
                <li>9</li>
            </ul>
            <script type="text/javascript">
                var lis = document.getElementsByTagName("li");
                for(var i = 0;i < lis.length;i++){
                    lis[i].onclick = function(){
                        console.log(i)
                    }
                            }
                     </script>

      如上所示,我们想要点击某一个数时后台打印出其对应的数字,粗略来看,上述逻辑好像并没有什么问题,但不管点击什么打印出来都只是10.

      那么这是为什么呢?

        因为在我们点击之前,全局已经生成了作用域GO,此时因为循环已经完成,生成的GO中变量i的最后赋值肯定是为10,然而当我们点击触发时间函数时所生成的作用域AO中没有关于i的定义,只能返回父级寻找,所以这时找到的i值就为10.

      

      那么怎么解决呢?

            <ul>
                <li>0</li>
                <li>1</li>
                <li>2</li>
                <li>3</li>
                <li>4</li>
                <li>5</li>
                <li>6</li>
                <li>7</li>
                <li>8</li>
                <li>9</li>
            </ul>
            <script type="text/javascript">
                var lis = document.getElementsByTagName("li");
                for(var i = 0;i < lis.length;i++){
                    (function(i){   
                        lis[i].onclick = function(){
                            console.log(i)
                        }
                    })(i)
                }
                    </script>

        如上所示,将点击事件函数装在一个立即执行函数中,形参实参都为i,这时每一次循环所生成的函数参数都为列表所对应的值,那么这所生成的所有函数的AO中都会有其所对应的i值,而这些函数正是我们点击事件函数的父级,所以这时我们再去点击触发时返回父级所寻找的i值即为我们想要的值。

    以上简单的列举了闭包的一些简单用法,闭包具体的应用还有很多很多,学无止境。

      

  • 相关阅读:
    【C语言期末实训】学生学籍管理系统
    【我要学python】愣头青之小数点精度控制
    【吾爱破解第二期】操作学习笔记
    【吾爱破解第一期】破解基础知识之认识壳与程序的特征
    【linux入门必备】小白需要掌握的基础知识_不定期更新
    【我要学python】爬虫准备之了解基本的html标签
    【我要学python】愣头青之初安装就打了一记耳光
    【我要学python】MethodType和isinstance和Type函数
    【我要学python】面对对象编程之继承和多态
    【我要学python】open函数的简单用法
  • 原文地址:https://www.cnblogs.com/lznzxy/p/10138593.html
Copyright © 2020-2023  润新知