zoukankan      html  css  js  c++  java
  • 闭包的用心总结

    十点读书佳句:我爱你,不光是因为你的样子,还因为和你在一起,我的样子。

    对于闭包一直没有系统化的去理解它,借此好好梳理一下思维加深理解:

    一、什么是闭包

    定义:定义在一个函数内部的函数。本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁

    解释:要理解这句话,首先明白js中的变量作用域。

    变量的作用域无非就是两种:全局变量和局部变量。

    js语言中,函数内部可以直接读取函数外部的全局变量,而函数外部却无法读取函数内部的变量。

    那么如何获取函数内部的变量呢,那就是在函数内部,在定义一个函数,这个函数可以拿到它上一级函数的变量,接着把这个函数当成返回值返回,就可以拿到定义在函数内部的变量

    实例:

    function fun1(){
      var a=100
      return function fun2(){
        console.log(a)
      }
    }
    var result=fun1()//这个时候返回的是fun2函数
    result()//再次调用 打印输出 100

    注意点:函数内部声明变量的时候,一定要使用var  如果不用的话,实际上声明了一个全局变量

     function fun(){
        var  a=100
        }
        fun()
       console.log(a) //undefined
    如果不用 var 变量声明 a 就变成了全局变量
    function fun(){ a=100 } fun() console.log(a) //100

    二、闭包的用途

    最大用处有两个:①可以读取函数内部的变量

            ②就是让函数内部变量的值始终保存在内存中 ,在函数外可以多次操作函数内的某个数据

    如何理解第二句话:

    实例:

     1、 普通函数:
    function fun1(){
    var num=Math.random() return num } console.log(fun1()) //0.4369938417433006 console.log(fun1()) //0.348201884591129
    打印 发现两次打印的结果不一致
    因为在每次调用后,num的值会被自动清除
    2、闭包:
      function fun1(){
          var num=Math.random()
          return function fun2(){
            console.log(num)
          }
        }
        var result=fun1()
        result()//0.5667691624507012
        result()//0.5667691624507012
    这次打印的结果就相同了
    为什么会这样呢?原因就在于fun1是fun2的父函数,而fun2被赋给了一个全局变量,这导致fun2始终在内存中,而fun2的存在依赖于fun1,
    因此fun1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收
    垃圾回收机制:将没有用的数据,不存在依赖关系的变量清除掉
     

    三、闭包的优点

    ①实现封装,减少全局变量命名冲突

    ②保存自己的私有变量

    ③可以读取函数内部的变量

    四、闭包的缺点,使用时注意的问题

    1)内存泄露:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

    2)闭包会在父函数外部,改变父函数内部变量的值。不要随意改变父函数内部的值

    五、思考题

    例一:
    var
    num = 100;   var object = { num : 200,     getNum : function(){       return function(){         return this.num;       };     }   };   alert(object.getNum()());

     例二:
    var num = 100;   var object = { num: 200, getNum: function () { var that = this       return function () {         return that.num;       };     }   };    alert(object.getNum()());

    六、点赞案例

    <body>
        <button>赞(0)</button>
        <button>赞(0)</button>
        <button>赞(0)</button>
        <button>赞(0)</button>
    
        <script>
            //功能描述:点击每个点赞按钮,赞数增加
            //1 获取元素
            var btns = document.getElementsByTagName("button");
            //2 设置一个赞数的值,点击后修改
            function fun(){
                //私有变量count,用于记录赞数,默认值为0
                var count = 0;
                //通过返回值的形式返回
                return function (){
                    //每次触发后,赞数+1
                    count++;
                    //console.log(count);
                    //设置某个btn的文字内容
                    this.innerText = "赞("+count+")";
                };
            }
    
        for(var i = 0; i < btns.length; i++){
                //将fun()的返回值保存在每个按钮的点击事件中
                //每次点击按钮时,相当于执行返回值函数
    
                //3 修改按钮的内容值
                // - 计数的值在返回值函数中,操作也需要在其中完成
                // - 如何在返回值函数中去操作当前的按钮呢?
                // - 通过调用的形式分析,发现this可以访问当前按钮,进行设置即可
                /*btns[i].onclick = function (){
                    //每次触发后,赞数+1
                    count++;
                    //设置某个btn的文字内容
                    this.innerText = "赞("+count+")";
                };*/
                btns[i].onclick = fun();
        }
        </script>
    </body>

     

  • 相关阅读:
    网卡驱动引起openstack的mtu问题
    Ironic几种不同的场景下的网络拓扑
    enable multi-tenancy on openstack pike
    galera断电后无法重建集群
    Fabric单节点安装备忘
    OpenStack Ironic 常见问题
    Enable multi-tenancy on ironic
    kolla-ansible快速入门
    kolla管理openstack容器
    d2.js学习笔记(七)——动态SVG坐标空间
  • 原文地址:https://www.cnblogs.com/shengmo/p/8687409.html
Copyright © 2011-2022 走看看