經(jīng)典閉包題解析
問:
下面代碼中,標(biāo)記?的地方輸出分別是什么?
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);??//??
解析:
一、a
var?a?=?fun(0);a.fun(1);a.fun(2);a.fun(3);
第一個(gè)fun(0)調(diào)用的是第一層函數(shù),同時(shí)返回了一個(gè)閉包對象,即:
function?fun(n?=?0,?o?=?undefined)?{
??console.log(o)??//?undefined
??return?...
}
所以這時(shí)候控制臺會(huì)打印undefined,并且這時(shí)a={ fun: function(m) }
接下來執(zhí)行a.fun(1),這時(shí)候會(huì)調(diào)用第二層匿名函數(shù),也就是:
{
????fun:function(m?=?1){
??????return?fun(m?=?1,?n?=?0);
????}
}
形參m = 1,并且再次調(diào)用第一層函數(shù),這時(shí)候n已經(jīng)在第一層函數(shù)時(shí)變?yōu)榱?code style="font-size:14px;font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(30,107,184);background-color:rgba(27,31,35,.05);">0,所以形參o = 0,即:
function?fun(n?=?1,?o?=?0)?{
??console.log(o)??//?0
??return?...
}
接下來執(zhí)行a.fun(2),同上一樣,只會(huì)改變m的值,n的值并不會(huì)改變,所以:
{
????fun:function(m?=?2){
??????return?fun(m?=?2,?n?=?0);
????}
}
function?fun(n?=?2,?o?=?0)?{
??console.log(o)??//?0
??return?...
}
a.fun(3)也一樣:
{
????fun:function(m?=?3){
??????return?fun(m?=?3,?n?=?0);
????}
}
function?fun(n?=?3,?o?=?0)?{
??console.log(o)??//?0
??return?...
}
所以得出第一個(gè)答案
a:?undefined,0,0,0
二、b
var?b?=?fun(0).fun(1).fun(2).fun(3);
第一個(gè)fun(0)調(diào)用的是第一層函數(shù),同時(shí)返回了一個(gè)閉包對象,即:
function?fun(n?=?0,?o?=?undefined)?{
??console.log(o)??//?undefined
??return?...
}
所以這時(shí)候控制臺會(huì)打印undefined,并且這時(shí)b={ fun: function(m) }
接下來執(zhí)行.fun(1),這時(shí)候會(huì)調(diào)用第二層匿名函數(shù),也就是:
{
????fun:function(m?=?1){
??????return?fun(m?=?1,?n?=?0);
????}
}
形參m = 1,并且再次調(diào)用第一層函數(shù),這時(shí)候n已經(jīng)在第一層函數(shù)時(shí)變?yōu)榱?code style="font-size:14px;font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(30,107,184);background-color:rgba(27,31,35,.05);">0,所以形參o = 0,即:
function?fun(n?=?1,?o?=?0)?{
??console.log(o)??//?0
??return?...
}
接下來執(zhí)行.fun(2),會(huì)調(diào)用第二層匿名函數(shù),并且第二層匿名函數(shù)中閉包了第一層函數(shù),這時(shí)形參n已經(jīng)由第一層函數(shù)時(shí)變?yōu)榱?code style="font-size:14px;font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(30,107,184);background-color:rgba(27,31,35,.05);">1,即:
{
????fun:function(m?=?2){
??????return?fun(m?=?2,?n?=?1);
????}
}
function?fun(n?=?2,?o?=?1)?{
??console.log(o)??//?1
??return?...
}
接下來的.fun(3)同上一樣:
{
????fun:function(m?=?3){
??????return?fun(m?=?3,?n?=?2);
????}
}
function?fun(n?=?3,?o?=?2)?{
??console.log(o)??//?2
??return?...
}
所以得出第二個(gè)答案
b:?undefined,0,1,2
三、c
var?c?=?fun(0).fun(1);c.fun(2);c.fun(3);
第一個(gè)fun(0)調(diào)用的是第一層函數(shù),同時(shí)返回了一個(gè)閉包對象,即:
function?fun(n?=?0,?o?=?undefined)?{
??console.log(o)??//?undefined
??return?...
}
所以這時(shí)候控制臺會(huì)打印undefined,并且這時(shí)c={ fun: function(m) }
接下來執(zhí)行.fun(1),這時(shí)候會(huì)調(diào)用第二層匿名函數(shù),也就是:
{
????fun:function(m?=?1){
??????return?fun(m?=?1,?n?=?0);
????}
}
形參m = 1,并且再次調(diào)用第一層函數(shù),這時(shí)候n已經(jīng)在第一層函數(shù)時(shí)變?yōu)榱?code style="font-size:14px;font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(30,107,184);background-color:rgba(27,31,35,.05);">0,所以形參o = 0,即:
function?fun(n?=?1,?o?=?0)?{
??console.log(o)??//?0
??return?...
}
接下來執(zhí)行c.fun(2),這時(shí)候會(huì)調(diào)用第二層匿名函數(shù),也就是:
{
????fun:function(m?=?2){
??????return?fun(m?=?2,?n);
????}
}
形參m = 2,并且再次調(diào)用第一層函數(shù),這時(shí)候形參n已經(jīng)在執(zhí)行.fun(1)時(shí)變?yōu)榱?code style="font-size:14px;font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(30,107,184);background-color:rgba(27,31,35,.05);">1,所以形參o = 1,即:
function?fun(n?=?2,?o?=?1)?{
??console.log(o)??//?1
??return?...
}
接下來執(zhí)行c.fun(3),同上一樣:
{
????fun:function(m?=?3){
??????return?fun(m?=?3,?n);
????}
}
形參m = 3,并且再次調(diào)用第一層函數(shù),這時(shí)候形參n已經(jīng)在執(zhí)行.fun(1)時(shí)變?yōu)榱?code style="font-size:14px;font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(30,107,184);background-color:rgba(27,31,35,.05);">1,所以形參o = 1,即:
function?fun(n?=?2,?o?=?1)?{
??console.log(o)??//?1
??return?...
}
注意:c,fun(2)和c.fun(3)是分開執(zhí)行的,都沒有改變c的值,所以這兩個(gè)函數(shù)并不會(huì)影響傳入的參數(shù)n
所以得出第三個(gè)答案
c:?undefined,0,1,1