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调用到了外部。

原文地址:https://www.cnblogs.com/chenyi4/p/13207182.html