由于最近在學(xué)習(xí)關(guān)于閉包相關(guān)的知識,并且閉包這個(gè)知識點(diǎn)讓我有點(diǎn)搞不太清楚其具體的定義,所以在網(wǎng)上也查閱了很多大佬的講解和對閉包的一個(gè)定義。
?
最后感覺還是MDN上的說法感覺比較好理解一些,對閉包還是不太理解的道友可以嘗試看一看。
MDN上是這樣說的:閉包是函數(shù)和聲明該函數(shù)的詞法環(huán)境的組合
原地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
<https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures>
?
在了解閉包的過程中遇到一個(gè)很多地方都出現(xiàn)的一個(gè)面試題,按照自己的想法想了下發(fā)現(xiàn)幾乎沒對...所以就花了些時(shí)間分析了一下,供自己以后忘記了可以回顧一下。
同時(shí),如果這里依舊存在一些誤區(qū),希望各位大佬們在評論區(qū)幫忙指正,感激萬分!
?
原題如下:
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); // ?
有興趣的道友們也可以試著先想一想答案,看下是否一致?
?
以下是解題思路:
1. 首先我對這個(gè)題畫了下題目中兩個(gè)fun函數(shù)中的一些信息 (可能不太完整,但是解題應(yīng)該夠用了)
2. 當(dāng)執(zhí)行 var a = fun(0);
時(shí),內(nèi)存中開辟了一塊新的空間給這個(gè)新的對象,這個(gè)對象中定義了一個(gè)方法fun。并且在fun(0)執(zhí)行時(shí),在當(dāng)前作用域下的變量信息如下:
?
因此,當(dāng)該語句執(zhí)行時(shí),控制臺打印的值為 undefined
?
3. 當(dāng)執(zhí)行 a.fun(1) 時(shí),因?yàn)閷ο骯中的fun方法在定義時(shí)所處的環(huán)境( [[scope]] )中存在一個(gè)變量n和變量o,
并且在這條語句執(zhí)行的時(shí)候,變量n( 此時(shí)n的值為0 ) 被第三方
(除了函數(shù)fun和方法fun)引用了,也就是被外部的對象a引用了,因此產(chǎn)生了Closure(閉包)。
然后,這條語句的return執(zhí)行的時(shí)候先執(zhí)行 調(diào)用fun函數(shù)----> 把m的值傳遞給了fun函數(shù)中的n,把n傳遞給了fun函數(shù)中的o,
因此控制臺中打印o的結(jié)果為0。
然而事情并沒有結(jié)束,調(diào)用fun函數(shù)會返回一個(gè)新的對象,這個(gè)對象也會在內(nèi)存中新開辟一個(gè)空間,而
此時(shí)這個(gè)新對象中的方法fun被定義時(shí)所處環(huán)境中的變量n已經(jīng)被賦值為m的值,也就是1了。
4. 當(dāng)a.fun(2)執(zhí)行的時(shí)候,發(fā)生了和上面一樣的故事,并且內(nèi)存中又被返回了一個(gè)新的對象且
這個(gè)新對象中的方法fun被定義時(shí)所處環(huán)境中的變量n已經(jīng)被賦值為m的值,也就是2
5. a.fun(3)執(zhí)行同上,且這個(gè)新對象中的方法fun被定義時(shí)所處環(huán)境中的變量n已經(jīng)被賦值為m的值,也就是3
故: a.fun(2) 和 a.fun(3)
在控制臺中打印o的結(jié)果都為0,且不管你傳的參數(shù)是多少,只要你沒有改變a對象的值,那么輸出的結(jié)果都是0,因?yàn)槟銈鞯膮?shù)都存在新的對象中了。
?
當(dāng)時(shí)我這里存在一個(gè)疑問,每次執(zhí)行n的值不是都被修改了嗎,為什么結(jié)果都是0呢?
注意:因?yàn)槟闶冀K都是在調(diào)用a的方法,而你每次執(zhí)行a的方法fun的時(shí)候又沒有把新返回的對象重新賦值給a,所以a里面的fun方法被定義時(shí)所處環(huán)境中的變量n一直都是0
?
6. 當(dāng)?var b = fun(0).fun(1).fun(2).fun(3); 執(zhí)行的時(shí)候就和上面疑問中的情形是一樣的了。
當(dāng) fun(0)執(zhí)行的時(shí)候,同上面a.fun(0)一樣,返回結(jié)果是undefined,且此時(shí)產(chǎn)生的新對象中,方法fun被定義時(shí)所處環(huán)境中的變量n為0
當(dāng) fun(1)執(zhí)行的時(shí)候,相當(dāng)于上面的a.fun(1)一樣,都是輸出0 (此時(shí)fun方法所處環(huán)境中的n為0),且返回一個(gè)新對象,新對象中的變量n為1
當(dāng)fun(2)執(zhí)行的時(shí)候,就不太一樣了,因?yàn)槭窃谇耙粭l語句執(zhí)行結(jié)果后面直接調(diào)用fun方法,
但此時(shí)的fun方法已經(jīng)不再是fun(1)中的方法了,而是上面返回的新對象中的方法,也就是變量n為1的方法,
所以,這里輸出的結(jié)果為1,且返回一個(gè)新對象,新對象中的變量n為2
當(dāng)fun(3)執(zhí)行的時(shí)候,和fun(2)的情況一樣,輸出結(jié)果為新的對象中的n,也就是2
?
7. 到這里,var c = fun(0).fun(1); 應(yīng)該就能夠明白為什么這里輸出對的結(jié)果是 undefined 和 0 了
因?yàn)榈览砗颓懊嬉粯?,第一個(gè) fun(0) 給n傳遞了值,但是o沒有,所以打印o的結(jié)果為undefined,第二個(gè) fun(1) 將n的值傳給了o,
所以打印的結(jié)果為0,且這里產(chǎn)生的對象被賦值給了變量c,此時(shí)方法fun被定義時(shí)的環(huán)境(也就是它的詞法作用域)中的n是被重新賦值的1
(方法fun的形參m把被傳過來的實(shí)參1,傳遞給了函數(shù)fun中的形參n)
故:c.fun(2) 和 c.fun(3)中c對象的fun方法被定義時(shí)的環(huán)境中的n都是1,所以輸出的結(jié)果也是把n的值傳遞給fun函數(shù)中的o, 即輸出1
?
此處是測試結(jié)果圖:
熱門工具 換一換