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);
//undefined,0,0,0
var b = fun(0).fun(1).fun(2).fun(3);//undefined,0,1,2
var c = fun(0).fun(1); c.fun(2); a.fun(3);//undefined,0,1,0
最近在網路上學習JS高級,但是閉包的這題我搞不懂
來源:
https://www.bilibili.com/video/BV14s411E7qf/?p=36
console.log(o),我這邊改成console.log(m,o),可以知道
var a = fun(0);a.fun(1); a.fun(2); a.fun(3);
0,1,2,3都傳給了m,而o一開始是undefined,
閉包=>
內部函數function(m){return fun(m,n);}
引用了外部函數的數據console.log(o)
o一開始就是undefined,也一直沒有傳數據進去,
a.fun(1); a.fun(2); a.fun(3);為什麼o會變成0?
下面的
var b = fun(0).fun(1).fun(2).fun(3);//undefined,0,1,2
var c = fun(0).fun(1); c.fun(2); a.fun(3);//undefined,0,1,0
這部分我也搞不懂
我後來用答案推演過程,大概知道原因。
var a = fun(0);是傳值function fun(n,o){console.log(o)...
n=0,o=undefined
後面的a.fun(1); a.fun(2); a.fun(3);是直接執行
fun:function(m){return fun(m,n);然後再return
所以1,2,3都是傳m;
n則是抓外部原本就存在的n=0,return 後n都是以0的值傳給o
所以console.log(o)就會一直是 0
但是靠事後諸葛,閉包這塊感覺跟不懂還是一樣,不曉得有沒有大老能夠講解。
要理解這個,首先你要知道階層的概念,var a = fun(0)
這行宣告之後,要有以下概念
a.n => 0
a.o => undefined (output)
a.fun => 新的fun(輸入值1, a.n)
然後,a.fun可以無限往下長,以此類推:
a.n => 0
a.o => undefined (output)
a.fun => 新的fun(輸入值1, a.n)
| a.fun.n => 輸入值1
| a.fun.o => a.n (output)
| a.fun.fun => 新的fun(輸入值2, 輸入值1)
| ...
| ...
| ...
有了這種階層概念,就會比較好理解為什麼輸出會是那樣。
a = fun(0)
=> undefined (因為沒有給值)a.fun(1)
=> a.n (一開始的輸入 : 0)a.fun(2)
=> a.n (一開始的輸入 : 0)a.fun(3)
=> a.n (一開始的輸入 : 0)
var b = fun(0)
=> undefined (因為沒有給值)var b = fun(0).fun(1)
=> a.n (上一行的輸入 : 0)var b = fun(0).fun(1).fun(2)
=> 輸入值1 (上一行的輸入 : 1)var b = fun(0).fun(1).fun(2).fun(3)
=> 輸入值2 (上一行的輸入 : 2)
var c = fun(0).fun(1)
=> undefined, 0 (同第二題)c.fun(2)
=> 1 (因為c是被賦予fun(1)的結果,所以根據fun(1)作為上一階繼續)a.fun(3)
=> 0 (同第一題)
其實我最不明白的是
a = fun(0)
function fun(n,o)//n=0,o=undefined
為什麼
fun(1)的時候
function(m){return fun(m,n);}
m=1這沒問題;但n=0,
如果說n的值抓的是function fun(n,o)的n值(同名稱)?
那return的時候,為什麼n值是傳給o(同位置)
是不是我基礎沒搞好QQ
我大概知道你的問題了。
這個範例在return時,是回傳一個function,而不是數值,在其他語言中比較通用的稱呼應該是叫做lambda
。這是一個將function當作變數來傳遞和使用的招數,最為經典的應該要屬lisp
這個語言。
lambda簡單的用法也可以像下面這樣:
function test(a, b){
return {
Add:function(){console.log(a + b)}
}
}
test(1, 2).Add()
如果你直接呼叫test(1, 2).Add
,那你會得到一個函數,這證明了該參數的值其實是一整個function,而加上()
的目的是為了將他視為函數去執行。
如果說n的值抓的是function fun(n,o)的n值(同名稱)?
還記得我說的階層概念嗎,由於回傳的是一個function,並不是數值,所以直到你呼叫這個回傳的function才會開始執行程式碼,會一路從children呼叫回去parent去要資料,這是callback
的部分,學JS要讀熟這塊才行。
階層概念有大概之後,再去理解這題的程式碼,就會知道這程式碼只是一個children顯示parent的參數的小程式。
所以以第一題來說,fun(1)、fun(2)、fun(3)都是fun(0)的child,顯示的就會是fun(0)的參數n
第二題的狀況就是:fun(0)生下fun(1)生下fun(2)生下fun(3)
所以顯示的就會是undefined、0、1、2
當你一、二題都完全理解,第三題就是送分了。