js闭包 典型举例

来源:互联网 发布:线切割hl绘图编程 编辑:程序博客网 时间:2024/06/09 19:46
  1. 闭包:指一个变量在他自身作用域外被使用了,就叫发生了闭包。
    如下:

    function fun(n,o) {  console.log(o)  return {    fun:function(m){      return fun(m,n);    }  };}var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?//问:三行a,b,c的输出分别是什么?

    代码中有三层的嵌套,我们注意到,如果第一次传入的只有一个参数,那么返回的函数会将这个参数n传到返回的函数中去,所以结果可想而知。

    //答案:
    //a: undefined,0,0,0
    //b: undefined,0,1,2
    //c: undefined,0,1,1

    具体解析如下:

    • 第一行a

      var a = fun(0); a.fun(1); a.fun(2); a.fun(3);

      可以得知,第一个fun(0)是在调用第一层fun函数。第二个fun(1)是在调用前一个fun的返回值的fun函数,所以:

      第后面几个fun(1),fun(2),fun(3),函数都是在调用第二层fun函数。

      遂:

      在第一次调用fun(0)时,o为undefined;

      第二次调用fun(1)时m为1,此时fun闭包了外层函数的n,也就是第一次调用的n=0,即m=1,n=0,并在内部调用第一层fun函数fun(1,0);所以o为0;

      第三次调用fun(2)时m为2,但依然是调用a.fun,所以还是闭包了第一次调用时的n,所以内部调用第一层的fun(2,0);所以o为0

      第四次同理;

      即:最终答案为undefined,0,0,0

    • 第二行b

      var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?

      先从fun(0)开始看,肯定是调用的第一层fun函数;而他的返回值是一个对象,所以第二个fun(1)调用的是第二层fun函数,后面几个也是调用的第二层fun函数。

      遂:

      在第一次调用第一层fun(0)时,o为undefined;

      第二次调用 .fun(1)时m为1,此时fun闭包了外层函数的n,也就是第一次调用的n=0,即m=1,n=0,并在内部调用第一层fun函数fun(1,0);所以o为0;

      第三次调用 .fun(2)时m为2,此时当前的fun函数不是第一次执行的返回对象,而是第二次执行的返回对象。而在第二次执行第一层fun函数时时(1,0)所以n=1,o=0,返回时闭包了第二次的n,遂在第三次调用第三层fun函数时m=2,n=1,即调用第一层fun函数fun(2,1),所以o为1;

      第四次调用 .fun(3)时m为3,闭包了第三次调用的n,同理,最终调用第一层fun函数为fun(3,2);所以o为2;

      即最终答案:undefined,0,1,2

    • 第三行c

      var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined,?,?,?

      根据前面两个例子,可以得知:

      fun(0)为执行第一层fun函数,.fun(1)执行的是fun(0)返回的第二层fun函数,这里语句结束,遂c存放的是fun(1)的返回值,而不是fun(0)的返回值,所以c中闭包的也是fun(1)第二次执行的n的值。c.fun(2)执行的是fun(1)返回的第二层fun函数,c.fun(3)执行的也是fun(1)返回的第二层fun函数。

      遂:

      在第一次调用第一层fun(0)时,o为undefined;

      第二次调用 .fun(1)时m为1,此时fun闭包了外层函数的n,也就是第一次调用的n=0,即m=1,n=0,并在内部调用第一层fun函数fun(1,0);所以o为0;

      第三次调用 .fun(2)时m为2,此时fun闭包的是第二次调用的n=1,即m=2,n=1,并在内部调用第一层fun函数fun(2,1);所以o为1;

      第四次.fun(3)时同理,但依然是调用的第二次的返回值,遂最终调用第一层fun函数fun(3,1),所以o还为1

      即最终答案:undefined,0,1,1

  2. 上述中涉及到的函数作用域链问题
    在函数表达式内部能不能访问存放当前函数的变量。
    对象内部的函数表达式:

    var o={  fn:function (){    console.log(fn);  }};o.fn();//ERROR报错   fn is not defined

    非对象内部的函数表达式:

    var fn=function (){  console.log(fn);};fn();//function (){console.log(fn);};正确

    结论是:使用var或是非对象内部的函数表达式内,可以访问到存放当前函数的变量;在对象内部的不能访问到。

    原因也非常简单,因为函数作用域链的问题,采用var的是在外部创建了一个fn变量,函数内部当然可以在内部寻找不到fn后向上册作用域查找fn,而在创建对象内部时,因为没有在函数作用域内创建fn,所以无法访问。

    所以综上所述,可以得知,最内层的return出去的fun函数不是第二层fun函数,是最外层的fun函数。

    所以,三个fun函数的关系也理清楚了,第一个等于第三个,他们都不等于第二个。

0 0
原创粉丝点击