zoukankan      html  css  js  c++  java
  • 闭包函数

    闭包介绍参考:   https://blog.csdn.net/vuturn/article/details/44560717  (里面有介绍闭包会出现的内存泄漏问题,以及解决办法)

              http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

                https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript#%E9%97%AD%E5%8C%85(MDN技术文档)

    看两个例子:

    例1:

        var fo = (function (){
            var a = 99;
            return function(){
                return a;
            }
        })();
    console.log(fo);

    例2:

    var foo = ( function() {
            var secret = 'secret';
            // “闭包”内的函数可以访问 secret 变量,而 secret 变量对于外部却是隐藏的
            return {
                get_secret: function () {
                    // 通过定义的接口来访问 secret
                    return secret;
                },
                new_secret: function (new_secret) {
                    // 通过定义的接口来修改 secret
                    secret = new_secret;
                }
            };
        }());
        foo.get_secret (); // 得到 'secret'
        foo.secret; // Type error,访问不能
        foo.new_secret ('a new secret'); // 通过函数接口,我们访问并修改了 secret 变量
        foo.get_secret (); // 得到 'a new secret'

    1、内嵌函数:一个函数内部还有函数,就是内嵌函数。(重点:内嵌函数 不一定是闭包函数,闭包一定有内嵌函数在return后面)

    2、闭包是指在 JavaScript 中,内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。(注:由于js的垃圾回收机制,函数在执行结束,内部声明的变量都会清除,但是闭包不会清除,仍然存在内存中,所以内存消耗很大,不能滥用闭包)

    3、通常,一个函数(暂记为 makeAdder)执行到 return后,JavaScript 的垃圾回收器会在这时回收 函数 创建的作用域对象(暂记为 b)。但是闭包中  return  后 的函数(暂记为 adder)里面的变量,拥有一个指向作用域对象 b 的引用,

      最终,作用域对象 b 不会被垃圾回收器回收,直到没有任何引用指向函数 adder。

         个人理解:return 后的函数没有指向 作用域对象 b 的引用 或 return 后根本没有函数 就不叫闭包。

          (return 的值  只是一个普通对象,引用的值会马上赋值给这个对象,不会再指向作用域对象 b 。函数内的引用,只有执行函数时,才能获取这个变量的值。所以闭包函数中有指向作用域对象 b 的变量,执行完makeAdder函数,还不能被回收)

    4、 闭包突破了"链式作用域"结构规则,在外部通过接口还是可以访问到内部的变量。

    5、如果外部需要函数内的一个变量,则直接返回函数就可以,如例1所示;如果需要访问内部多个变量则返回必须是一个对象,如例2所示。

    总结:闭包的一个明显的特点,一定有return,且return中一定有函数(直接函数 或 对象中有函数)。

    闭包内存泄漏问题:(内存空间没有指针指向就会回收,出现循环引用才会导致内存泄露)

        https://www.cnblogs.com/greatluoluo/p/5930685.html

        如上面链接中例子:

    function leakMemory() {
        var el = document.getElementById('el');
        var obj= { 'el': el };
        el.obj= obj;
    }


    这段代码中(还不是闭包函数),函数中引用了外部的dom对象,同时, 函数中的 el.obj 给外部的dom对象添加了一个属性,引用了函数内的obj对象。
    这样就存在了相互引用的问题,js垃圾回收机制无法回收这个函数。
    function addHandler() {
        var el = document.getElementById('el');
        el.onclick = function() {
            el.style.backgroundColor = 'red';
        }
    }

    我们常常像这个例子中一样,在函数中给DOM对象创建事件,这样无意识中就存在内存泄漏问题。(个人觉得解决内存泄漏问题,可以把变量使用后设置为 null ,断开引用)

        https://www.cnblogs.com/yakun/p/3932026.html

        https://blog.csdn.net/johnny0991/article/details/51778436 (能导致内存泄漏的一定是引用类型的变量,而值类型的变量是不存在内存泄漏的)

  • 相关阅读:
    Object的create、assign、getPrototypeOf与拷贝
    vue中使用axios最详细教程
    COJ1249(竞争性酶抑制剂和同工酶)
    COJ1127(芝麻开门)
    COJ1219(建食堂)
    COJ1236(删数游戏)
    COJ1247(有髓鞘神经纤维动作电位传导)
    POJ1159(Palindrome)
    POJ1080(Human Gene Functions)
    Uva10034(Freckles)
  • 原文地址:https://www.cnblogs.com/wfblog/p/8951886.html
Copyright © 2011-2022 走看看