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

  • 相关阅读:
    windows下安装mysql(mysql-installer-community-5.6.10.1)
    mysql安装
    Full GC为什么那么慢?为什么老年代垃圾回收效率比新生代低很多?为什么Minor gc速度比Major GC慢?
    tomcat和HTTP(r equest response )
    response和request
    一次完整的Http请求过程
    servlet
    java泛型
    数据库索引的实现原理
    终端打印
  • 原文地址:https://www.cnblogs.com/chenyi4/p/13207182.html
Copyright © 2020-2023  润新知