理解闭包——闭包中包含递归
有如下代码:
function fun(n,o){ console.log(o); return { fun:function(m){ return fun(m,n); } }; }
这段代码中既有闭包,也有递归。
先看看这段代码的作用。外层fun(n,o){}函数的执行顺序是:
1、先输出函数的第二个参数o;
2、返回一个对象,该对象包含一个可用.操作符访问的fun方法。
一、执行函数
让我们执行如下语句:
这段语句的意思是:将fun(0)赋值给a,并调用a。这段语句的结果就是:
1、输出undefined;(因为赋值语句中没有给外层fun函数第二个参数,而输出语句输出的是第二个参数,所以输出结果是undefined)
2、返回一个对象,该对象包含一个fun方法。该方法接受一个输入参数m,返回一个函数fun()。这个内层函数有两个参数,第一个参数是输入参数m,第二个参数是外层函数的第一参数0。
注意:如果调用这个方法,那么相当于再执行一次外层函数fun,不过这次给fun输入了两个参数m,0。
二、第一次调用方法
那么我们就来调用该方法。语句如下:
因为调用a之后,a相当于是一个包含fun方法的对象,即{fun:function(m){return fun(m,0);}}。
那么a.fun(1)相当于是调用对象a的fun方法,并传入参数1。该方法是一个函数function(m){return fun(m,0)},该函数又返回一个函数fun(m,0)。
所以调用a.fun(1)相当于是执行函数fun(1,0)。执行结果就是:
1、输出0(此时第二个参数为0);
2、返回一个对象,该对象包含一个fun方法。该方法接受一个输入参数m,返回一个函数fun()。这个内层函数有两个参数,第一个参数是输入参数m,第二个参数是外层函数的第一参数1。
调用a的fun(1)方法后,此时a.fun(1)相当于是一个包含fun方法的对象。即{fun:function(m){return fun(m,1);}}。
三、第二次调用方法
那么我们就来调用a.fun(1)的fun方法。语句如下:
a.fun(1).fun(2)相当于是调用a.fun(1)这个对象的fun方法,并传入参数2。该方法是一个函数function(m){return fun(m,1);}
所以调用a.fun(1).fun(2)相当于是执行函数fun(2,1)。执行结果就是:
1、输出1(此时第二个参数为1);
2、返回一个对象。该对象包含一个fun方法。该方法接受一个输入参数m,返回一个函数fun()。这个内层函数有两个参数,第一个参数是输入参数m,第二个参数是外层函数的第一参数2。
调用a.fun(1)的fun(2)方法后,此时a.fun(1).fun(2)相当于是一个包含fun方法的对象。即{fun:function(m){return fun(m,2);}}
四、第三次调用方法
那么我们就来调用a.fun(1).fun(2)的fun方法。语句如下:
a.fun(1).fun(2).fun(3)相当于是调用a.fun(1).fun(2)的fun方法,并传入参数3。该方法是一个函数function(m){return fun(m,2);}。
所以调用a.fun(1).fun(2).fun(3)相当于是执行fun(3,2)。执行结果如下:
1、输出2(此时第二个参数是2);
2、返回一个对象。该对象的fun方法接受一个输入参数m,返回一个函数fun()。这个内层函数有两个参数,第一个是输入参数m,第二个参数是外层函数的第一个参数3。
这种调用方式称为链式调用。
我们再看如下代码:
由上可知,调用a,a相当于是一个对象{fun:function(m){return fun(m,0);}}。
所以a.fun(1)相当于执行fun(1,0)。所以输出0。然后返回对象{fun:function(m){return fun(m,1);}}。
所以a.fun(2)相当于执行fun(2,0)。所以输出0。然后返回对象{fun:function(m){return fun(m,2);}}。
所以a.fun(3)相当于执行fun(3,0)。所以输出0。然后返回对象{fun:function(m){return fun(m,3);}}。