zoukankan      html  css  js  c++  java
  • 通俗讲解闭包

    前言:什么是闭包?它有什么优点缺点?这是很多公司面试时候总是问的装逼问题,因为闭包这种东西其实我们大家都用过,就是不知道名词。网上的答案也是五花八门,有的答案啰嗦,有的答案过于简洁。至于优点缺点更是说的模棱两可,让人只知其意,不知其义。

    1.什么是闭包?

      说破了大天,其实就是:子函数用了父函数里面定义的参数、变量。

      闭包的原理:每个函数在声明并执行的时候,ECMAScript都会为该函数在作用域链上追加上一个该函数的作用域,该作用域中保存了该函数的 引用对象局部变量的指针,如果不存在闭包,那么每个函数的作用域都包含在window对象的这个大作用域中,当关闭浏览器,window这个东西才被销毁。而有了闭包,就会形成子函数的作用域被包在父函数的作用域中,而父函数的作用域又被包在了window中。当形成闭包的子函数调用参数的时候,会通过检索变量名称,逐级上溯。先找自身,再找父函数,没有再找window。

    2.怎么分辨闭包?

       但是闭包也不能靠是否函数包着函数来分辨,比如下面这个例子:

      

    var res = new Array();
            function creat() {
                for (var i = 0; i < 10; i++) {
                    res[i] = function () {
                        return i;
                    };
                }
            }
            creat();
            alert(res[2]());//输出10

     这里面虽然函数包着函数,但是在该作用域中,匿名函数并没有运行,只是起到了定义的作用,并作为一个变量赋值给了数组,而当数组再运行该匿名函数的时候,creat函数已经运行完毕,作用域中保存的都是变量的指针,而不是变量的值,所以当匿名函数运行返回i时,i已经指向10这个数值。
     而在creat中就运行匿名函数的时候,数组就会保存 0-9的数字,虽然用到了闭包,但是这跟我们数组保存函数这一初衷相违背,所以,我们可以在给数组赋值这一过程的时候给它加上闭包

    var res = new Array();
            function creat() {
                for (var i = 0; i < 10; i++) {
                    res[i] =function(num){ 
                      return  function () {
                            return num;
                         }
                      }(i);
                }
            }
            creat();
            alert(res[2]());//输出2

    这样大家就能理解闭包了吧。

    3.闭包的优点是啥?

    方便大家编程,函数嵌套省去了函数间来回来去的传参,我就不信

    function father(a,b){
       var arr=new Array();
       arr.push(a+b);
       arr.push(a-b);
       return arr;
    }
    function father2(){
        return father(3,2)[0]*father(3,2)[1];
    }
    alert(father2());//5

    这样写比这样写看着更简洁,更省代码量。

    function father(a, b) {
                function son() {
                    return (a + b) * (a - b);
                }
                return son();
            }
            alert(father(3,2));//5

    而且相互调用参数的层次以及函数作用域看得更为明显,保持变量在逻辑上的连贯性,而不是让人看传参看得眼花。保持了变量的私有性,极好的避免了变量重名冲突。方便了开发。

    4.闭包的缺点

    闭包的优点同时也是它的缺点,保持变量逻辑上的连贯性必然导致ECMAScript下函数作用域链的延长,占用内存空间。

    原因:函数包着函数就导致作用域链又加了一环,比如上述例子:

            方案一有两个函数作用域,但是二者没有指向关系,father函数执行完毕,作用域销毁,传递给father2数据,father2在执行完后销毁。

            方案二,father函数包着son函数,father执行时不同时启动了son函数,son函数的作用域引用了father作用域的变量对象,所以father函数得等着son函数执行并销毁完它才能销毁。

             还有缺点就是在变量的生存周期上,占用了内存。

            方案一:father执行完后,a,b作为非全局变量被销毁。

            方案二:father的a,b变量在等待son函数使用完a,b后才能销毁。

            

  • 相关阅读:
    Stream processing with Apache Flink and Minio
    Replicated Ship 本地 kubernetes 环境试用
    replicatedhq-ship 基于Kustomize 项目的快速kubernetes 应用部署工具
    kustomize 模版自由的配置&&自定义kubernetes工具
    hasura graphql-engine v1.0.0-alpha30 remote schema stitch 试用
    Modern Data Lake with Minio : Part 2
    Modern Data Lake with Minio : Part 1
    使用rclone 进行minio 文件同步
    hasura graphql-engine v1.0.0-alpha30 功能试用
    hasura graphql-engine v1.0.0-alpha30 版本新功能介绍
  • 原文地址:https://www.cnblogs.com/JhoneLee/p/3498378.html
Copyright © 2011-2022 走看看