• 我眼中的JavaScript闭包


    一、变量的作用域

      要理解闭包,首先必须理解Javascript特殊的变量作用域。

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

      JavaScript语言在函数内部可以访问外部的变量,但是在函数外部不可以使用函数内部的变量,也就是局部变量。

      在函数内部可以访问外部的变量。

      比如这样:

    var num=20;
    function func1(){   
      console.log(num);
    }
    func1(); //得到的值为20

      另一方面,在函数外部自然无法读取函数内的局部变量。

      比如这样:

    function func1(){
        var num=20;
    }
    console.log(num); // num is not defined(报错)

    二、如何在函数外部去得到局部变量的值

      有时候,我们想要去得到函数内部的变量,应该怎么办呢?我们可以在函数的内部,再定义一个函数,从而来达到我们的目的。

    function func1(){
        var num = 20;
        function func2(){
            return num
        }
        return func2;
    }
    var result = func1();    
    console.log(result()); //得到的值为20

      在上面的代码中,函数func2被包括在函数func1内部,这时func2可以调用func1中的所有局部变量。但是反过来就不行,func1不能调用func2内部的局部变量。这就是Javascript语言特有的作用域链。子级会一级一级地向上寻找所有父级的变量,最终找到全局变量为止。

      在这个段代码中,函数func2就是闭包。

    三、闭包的概念

      官方的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。相信很少有人能直接看懂这句话,因为他描述的太学术。

      我们可以简单地理解为,闭包就是能够读取其他函数内部变量的函数,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

    四、闭包的用途  

      闭包最大的用处有两个:

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

      ② 变量持久化,让变量的值始终保持在内存中

      如何来理解变量持久化呢?请看下面这段代码:

    function fn1(){
        var num = 18;
        function fn2(){
            return ++num;
        }
        return fn2;
    }
    var result = fn1();
    console.log(result());  //得到的值为19
    console.log(result());  //得到的值为20  
    console.log(result());  //得到的值为21     

      在这段代码中,result实际上就是闭包fn2函数。它一共运行了三次,第一次的值是19,第二次的值是20,第三次的值是21。这证明了,函数fn1中的局部变量num一直保存在内存中,并没有在fn1调用后被自动清除。

      为什么会这样呢?原因就在于fn1是fn2的父函数,而fn2被赋给了一个全局变量,这导致fn2始终在内存中,而fn2的存在依赖于fn1,因此fn1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

    五、闭包的优缺点

      优点:

        ① 逻辑连续,当闭包作为另一个函数调用的参数时,避免你脱离当前逻辑而单独编写额外逻辑。

        ② 方便调用上下文的局部变量。

      缺点:

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

      闭包和作用域有着密不可分的关系,真的是“想说爱你不容易”!

      全文完!

  • 相关阅读:
    STM32位带操作
    url参数 加密
    object.key 对象的键排序 可能出现的问题
    在vue项目中 获取容器的高度
    navigator 判断移动端是Android还是iOS
    Nginx下载地址
    Sublime Text3快捷键大全
    鼠标拖着元素飞
    g6 cavans
    vue img标签图片加载时 闪烁
  • 原文地址:https://www.cnblogs.com/mysun-shine/p/6534501.html
Copyright © 2020-2023  润新知