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

    闭包就是函数作用域是一个封闭的区域,作用域变量携带到外层,可以携带它对父作用域的变量的引用,不会被销毁

    最近在看 《JavaScript编程精粹》这本书,里面提到高级程序都会使用到闭包

    应用场景

    1.setTimeout的循环

    for(var i = 1; i < 5; i++){
            setTimeout(function(){
                console.log(i);
            },i*1000)
    }

    setTimeout 调用的function 是等待以后再去调用的,所以打印了4遍 5 的值。

    解决办法:把i值放在封闭的区域里面,function调封闭区域的变量,参数也是局部变量

    for(var i = 1; i < 5; i++){
            function set(i){
                setTimeout(function(){
                    console.log(i);
                },i*1000);
            }
            set(i);
        }

    输出结果: 1,2,3,4,5

    或者写成立即执行,(function(i){  })(i)

    都是把i 值丢在一个闭包里面,这样,setTimeout延迟执行后读的 i 也是function 里面的局部变量,因为i被固定到闭包里面了。 i和i之间不会互相被干扰。

    function add() {
        var counter = 0;
        return counter += 1;
    }
     
    add();
    add();
    add();

    因为闭包对局部变量的封闭,所以上面执行结果是1, 1, 1

    2.利用闭包实现私有变量

    function SetObj(){
            var value = 2;
            this.readValue = function(){
                return value;
            }
            this.add = function(){
                value = value + 1;
            }
        }
    
        var obj = new SetObj();
        obj.add();
        console.log(obj.readValue());
    
        var obj2 = new SetObj();
        obj2.add();
        obj2.add();
        console.log(obj2.readValue());

    因为js里面是不存在私有变量的概念的,java中的private

    所以利用闭包,可以让value不能被外部变量读取,也不能被随便更改,只能用作者设定的读取和写好的方法去修改这个变量。这样外部就无法读到这个变量。多个功能的实现,即使每个模块

    里面的变量和函数重名也没有关系,因为闭包和闭包之间的变量互相是不干扰的。

    jquery里面用到很多的闭包,就是避免外部使用者定义的变量去影响库里面自定义的变量,避免重名的风险。外部对方法的调用,也只能按照库约定的方式调用,并不能从调用的方法里面去影响内部的变量值。

    比如我们实现功能,定义一个全局的变量来计数,来统计点击的次数,那别的同事很可能会定义和你一样的变量,改改就不知道莫名其妙的报错了找不到哪里有问题。用闭包把这个方法封装起来,读取的时候也写对外的读取方法,就能避免这个问题。es6也有语法能实现这个功能,但是之前是利用闭包来解决这个问题的

    =================================================

    像上面的例子的闭包是有一个内存泄漏的问题的。因为闭包(比如function)内部的变量,内部的变量,function在立即执行后值是会被销毁的。但是如果它被全局变量引用了,那它的值就不会被销毁了。而且因为内部变量,能读取外部的值,是因为层层引用链的原因,它自己会携带一个很长的数据链。所以引用这个值不被销毁就算了,它所引用的数据链也不会被销毁的,也就说,这个函数外部只要被它所引用的数据,也全部都不会被销毁。

     举个例子

    var test;
       function aset(){
           var a = 22;
           var b = 12;
           test = function as(){
              return b;
           }
       }
       aset();
       var all = test();
    console.log(test.prototype);

    这里面test是一个闭包,它把它上级作用域的b变量携带着走了

    查看一下打印的结果

    test 的 原型 携带了一个scopes的数据链,显示了b变量 和全局变量  b 是属于closure(闭包)的值。可以看到test它携带的引用数据链值范围。闭包的值,在函数执行完毕也不会被销毁。因为它被test调用到了外部。

  • 相关阅读:
    牛客练习赛51 D题
    Educational Codeforces Round 72 (Rated for Div. 2) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Educational Codeforces Round 72 (Rated for Div. 2) B题
    Educational Codeforces Round 72 (Rated for Div. 2) A题
    《DSP using MATLAB》Problem 7.2
    《DSP using MATLAB》Problem 7.1
    《DSP using MATLAB》Problem 6.24
  • 原文地址:https://www.cnblogs.com/chenyi4/p/13207182.html
Copyright © 2011-2022 走看看