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.谁在调用谁?
可能看了上面的分析,你脑袋并没有清醒多少,没关系,现在来具体分析一下,到底是谁调用了谁。
第一行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
;第二行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
;第三行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.总结
关于闭包,这个概念其实并不难懂,网上对闭包也有各种各样的解答。真正难的是你如何能后去熟练的运用。在理解闭包的前提下,尝试着去融入自己的程序,久而久之,我们自然就会孰能生巧了。
文/听安静的时光(简书作者)