前情提要:昨晚看到一个闭包的题,就因为return了对象,然后出现了一系列的不同操作就打印出不同的值,感觉自己憨憨的,一下子没理解过来,还是对于“堆栈、树、节点”之类的理解太浅了,所以来记录一下思考过程吧!(虽然还是不理解树啊节点什么的…)
关于闭包,你是return一个函数呢?还是return一个对象呢?为什么要return对象?
带着这个疑问走下去吧
let’s go!!
function aa(n,o){
console.log(o,n)
return function(m){
aa(m,n)
}
}
同为闭包,将直接返回一个函数的闭包改为返回一个对象
这样可以使用“.”操作符来实现连续调用,创建更大的有存储效果的闭包空间
是不是真这么厉害??
看看就知道咯
ok,现在出现一个问题,使用".”操作符也会有不同的效果,如下的例一二三,为什么被打印出的o变量在三个例子中会有不一样的值呢?
function fun(n,o) {
console.log(n,o);
return {
fun:function(m) {
return fun(m,n);
}
};
}
var a = fun(0);
a.fun(1);
a.fun(2);
a.fun(3);
console.log('bbb')
var b = fun(0).fun(1).fun(2).fun(3);
console.log('cc')
var c = fun(0).fun(1);
c.fun(2);
c.fun(3);
先来补充点信息吧,能帮助下面更好的理解
- 先来看一看a里面的结构,ok 是一个对象,里面有一个fun函数
- a.fun(1)执行后实际上就是
调用了fun(1,0)【第二个参数0就是调用了信息库,信息库这个概念马上就解释啦】
打印了n,o
并return了一个对象,对象里面有fun函数
ok 进入正题!!咱们就用一个图来比喻一下这里面的逻辑吧。
你看例子a,
-
a = fun(0)创建了一个闭包,此时里面的信息库是 n=0,o=undefiend(我们就把蓝框框里的数据叫作信息库吧)
-
a.fun(1) 使用“.”操作符,表示在a这个闭包信息库下创建了又一层的闭包,实质调用了fun(1,0)【第二个参数就是从fun(0)信息库中获取的n的值啦】,此时里面的信息库是 n=1 ,o=0
插播一下,实质调用了fun(1,0) 是指这
-
同理,a.fun(2) 也使用了“.”操作符,也表示在a信息库下(也就是fun(0)信息库)创建的一层闭包,实质调用fun(2,0),此时里面的信息库n=2,o=0
-
同理得a.fun(3) 实质调用了fun(3,0),此时信息库n=3,o=0
为了加强理解,马不停蹄的再来看看例子c吧
- c = fun(0).fun(1),可以理解为例子a中的“a.fun(1)”嘛,那么此时的信息库是??对啦!直接把上面那个例子的搬下来嘛,就是n=1,o=0啦
- 然后是c.fun(2),上面说了“.”操作符 会在前面的信息库的基础上创建又一层的信息库,所以实质调用了fun(2,1)!!第二个参数就是拿到了c的信息库中的n=1啦,此时的信息库是n=2,o=1
- 同理,c.fun(3),也同样获取c信息库中的n=1,所以实质调用了fun(3,1),此时的信息库是n=3,o=1
这时候再回头看看例子b,是不是就很好理解了呢?
虽然看到这可以已经基本理解啦,还是啰啰唆唆的再叨叨一下吧
b = fun(0).fun(1).fun(2).fun(3)分开来说就是
- fun(0) 执行后的信息库 n=0,o=undefined
- ‘.’连接符表示以之前的信息库继续执行
- fun(1) 实质调用了fun(1,0)【第二个参数0表示获取到上层的信息库中的n=0】执行后的信息库 n=1,o=0
- 继续“.”操作,表示继续复用上面的闭包信息库,即 n=1,o=1
- fun(2) 实质调用了fun(2,1) 【第二个参数1表示获取到上层的信息库中的n=1】 执行后的信息库 n=2,o=1
- 继续”.“操作~~,表示继续使用新的信息库 n=2,o=1
- fun(3) 实质调用了fun(3,2) 【第二个参数0表示获取到上层的信息库中的n=0】此时信息库是n=3,o=2
怎么样??现在有没有变得更强了呢?