JavaScript--这道闭包题做起来有意思

0.前言

闭包的定义是什么?我一直觉得狭义上这么形容可能是更加的恰当:父函数包含子函数,并把子函数做为父函数的返回值,来达到保存父函数中局部变量的效果。
在工作的时候,使用闭包的时候还是挺多,不久前在逛博客园的时候,看到了一道关于闭包的题目,感觉确实不错。

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); 
 var b = fun(0).fun(1).fun(2).fun(3);
 var c = fun(0).fun(1);c.fun(2);c.fun(3);
请问 运行结果是什么?

题目的答案,我放在博客的末尾,众位看官不妨尝试着自己算一下输出结果。这道闭包题目,已经是属于具有一定难度,如果你能够上来就顺利的将这道题搞定。ok,相信闭包这方面,已经很少有能难倒你的了。

2.分析

如果你认真的思考了题目,好的,接下来的内容就是为你写的。如果你只是看了一眼的话,习惯性看解释的话,我建议你还是应该尝试着去做一做。

分析闭包结构:父函数fun,需传入两个参数n和o。运行结果返回一个对象。对象内部有一个属性fun(注意,这里的fun是对象的一个属性和函数fun不是一码事),fun属性的值为一个匿名函数(需要传入一个参数m),其调用结果则是返回一个fun函数,不过这个函数传入的参数是m和n;

总结一点,就是fun(n,o)返回对象,fun(n,o).fun(m)的结果=fun(m,n);

3.谁在调用谁?

可能看了上面的分析,你脑袋并没有清醒多少,没关系,现在来具体分析一下,到底是谁调用了谁。

  1. 第一行a

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

    首先,定义var a = fun(0);这一步也就是相当于调用了函数fun(0,o),n=0,o=?o的值我们没有给定,所以说这里o=undefined,打印的结果就是undefined;a的执行结果返回一个obj。

    a.fun(1);a.fun(2);a.fun(3);
    这里的a便是上面的对象obj,a.fun(1)即调用了匿名函数,返回fun(m,n),这里m=1,n=0,所以打印结果是0;

    后面同理,所以第一行执行结果是:undefined 0 0 0;

  2. 第二行b

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

    可以看到这一行,全部都是通过.连接,调用不同对象的fun属性,所以跟上面有一点不一样。

    var b =fun(0).fun(1)执行方式类似于var a = fun(0);a.fun(1);,所以会打印undefined 0

    继续向后走,var b =fun(0).fun(1).fun(2),运行到这里,fun(2)fun(1)则不是同一个对象的属性了,前者是var b =fun(0).fun(1)执行结果所返回的对象的属性,这样就会导致m和n的值一直在变化,所以打印的数值也会变化。

    所以,这一行执行结果是:undefined 0 1 2;

  3. 第三行c

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

    第三行,说白就是将前两行进行了一个结合,前面两行搞定了,第三行也就搞定了。

    第三行执行结果:undefined 0 1 1;

    所以:结果是
    undefined 0 0 0;
    undefined 0 1 2;
    undefined 0 1 1;

    4.总结

关于闭包,这个概念其实并不难懂,网上对闭包也有各种各样的解答。真正难的是你如何能后去熟练的运用。在理解闭包的前提下,尝试着去融入自己的程序,久而久之,我们自然就会孰能生巧了。



文/听安静的时光(简书作者)


上一篇: 一天精通 Chrome 开发

下一篇: 如何合理的规划前端之路

分享到: 更多