摘要:的本質(zhì)問(wèn)題其實(shí)就是詞法作用域的問(wèn)題或者說(shuō)是引擎如何在當(dāng)前作用域以及嵌套的子作用域中根據(jù)標(biāo)識(shí)符名稱進(jìn)行變量查找引擎查找標(biāo)識(shí)符位置的規(guī)則簡(jiǎn)而言之就是作用域查找會(huì)在找到第一個(gè)匹配的標(biāo)識(shí)符時(shí)停止換句話說(shuō)是作用域查找始終從運(yùn)行時(shí)所處的最內(nèi)部作用域開(kāi)始
Closure的本質(zhì)問(wèn)題其實(shí)就是詞法作用域的問(wèn)題, 或者說(shuō)是JavaScript引擎如何在當(dāng)前作用域以及嵌套的子作用域中根據(jù)標(biāo)識(shí)符名稱進(jìn)行變量查找.
JavaScript引擎查找標(biāo)識(shí)符位置的規(guī)則, 簡(jiǎn)而言之, 就是:
作用域查找會(huì)在找到第一個(gè)匹配的標(biāo)識(shí)符時(shí)停止
換句話說(shuō)是: 作用域查找始終從運(yùn)行時(shí)所處的最內(nèi)部作用域開(kāi)始, 逐級(jí)向外或者說(shuō)向上進(jìn)行, 知道遇見(jiàn)第一個(gè)匹配的標(biāo)識(shí)符為止
帶著以上的結(jié)論, 我們看看這個(gè)例子來(lái)驗(yàn)證一下:
function fun(n,o) { console.log(o) return { fun:function(m){ return fun(m,n); } }; } //Question 1 var a = fun(0); a.fun(1); a.fun(2); a.fun(3); //Question 2 var b = fun(0).fun(1).fun(2).fun(3); //Question 3 var c = fun(0).fun(1); c.fun(2); c.fun(3);
Question 1的答案和解釋
var a = fun(0); //undefined
a.fun(1); //0
a.fun(2); //0
a.fun(3); //0
Question 1.1
傳入n=0,并沒(méi)有傳入o, 所以是undefined。這個(gè)時(shí)候a是含有fun的object:
{ fun:function(m){ return fun(m,n); } }
Question 1.2
a包含的fun被trigger了, 傳入了n=1并且最終trigger了fun(m, n).
那么問(wèn)題來(lái)了, m和n分別是什么?
m是剛剛傳進(jìn)來(lái)的1, 這個(gè)很簡(jiǎn)單;
n只能根據(jù)作用域網(wǎng)上查找, 發(fā)現(xiàn)時(shí)上次傳進(jìn)來(lái)的一個(gè)形參, 它的值就應(yīng)該是上次傳進(jìn)來(lái)的0;
所以, 最終a.fun(1)是trigger了fun(1, 0), 最后的答案是0.
對(duì)于Question 1.3和1.4來(lái)說(shuō), 同理最終的答案也是0.
Question 2的答案和解釋
b = fun(0).fun(1).fun(2).fun(3)
//undefined
//0
//1
//2
根據(jù)Question 1.2的解釋 就很好理解這個(gè)答案了
Question 3的答案和解釋
var c = fun(0).fun(1); c.fun(2); c.fun(3);
//undefined
//0
//1
//1
根據(jù)Question 1.2的解釋 var c = fun(0).fun(1)會(huì)分別log出undefined和0
這個(gè)時(shí)候c應(yīng)該是含有fun的object:
{ fun:function(m){ return fun(m,n); } }
當(dāng)c.fun(2)的時(shí)候 其實(shí)也是trigger了fun(m, n).
m是當(dāng)前傳入的2. n由于沒(méi)有被傳入, 只能向外作用域?qū)ふ? 發(fā)現(xiàn)上次傳入的n且n=1.
所以最后log的值為1.
同理對(duì)于c.fun(3) 最后log的值也為1.
總結(jié)
通過(guò)理解JavaScript引擎向上查找作用域的規(guī)則 可以更好的讓我們理解Closure
Reference:
你不一定能做對(duì)的JavaScript閉包面試題
You Don"t Know JS: Scope & Closures
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/88418.html
溫馨提示:作者的爬坑記錄,對(duì)你等大神完全沒(méi)有價(jià)值,別在我這浪費(fèi)生命 這一切,源于阮大神博文學(xué)習(xí)Javascript閉包(Closure)- 阮一峰中的一道思考題 //問(wèn)題1: var name = The Window; var object = { name : My Object, getNameFunc : function(){ return function(){ ...
摘要:當(dāng)初看這個(gè)解釋有點(diǎn)懵逼,理解成閉包就是函數(shù)中的函數(shù)了。里的閉包最近不滿足于只干前端的活,開(kāi)始用起了。里的閉包最近在學(xué)習(xí)語(yǔ)言,讓我們來(lái)看一下語(yǔ)言里的閉包。在中,閉包特指將函數(shù)作為值返回的情況,被返回的函數(shù)引用了生成它的母函數(shù)中的變量。 本人開(kāi)始接觸編程是從js開(kāi)始的,當(dāng)時(shí)網(wǎng)上很多人說(shuō)閉包是難點(diǎn),各種地方對(duì)閉包的解釋也是千奇百怪。如今開(kāi)始接觸js以外的各種編程語(yǔ)言,發(fā)現(xiàn)不光是js,php、...
摘要:當(dāng)初看這個(gè)解釋有點(diǎn)懵逼,理解成閉包就是函數(shù)中的函數(shù)了。里的閉包最近不滿足于只干前端的活,開(kāi)始用起了。里的閉包最近在學(xué)習(xí)語(yǔ)言,讓我們來(lái)看一下語(yǔ)言里的閉包。在中,閉包特指將函數(shù)作為值返回的情況,被返回的函數(shù)引用了生成它的母函數(shù)中的變量。 本人開(kāi)始接觸編程是從js開(kāi)始的,當(dāng)時(shí)網(wǎng)上很多人說(shuō)閉包是難點(diǎn),各種地方對(duì)閉包的解釋也是千奇百怪。如今開(kāi)始接觸js以外的各種編程語(yǔ)言,發(fā)現(xiàn)不光是js,php、...
摘要:譯者按在上一篇博客,我們通過(guò)實(shí)現(xiàn)一個(gè)計(jì)數(shù)器,了解了如何使用閉包,這篇博客將提供一些代碼示例,幫助大家理解閉包。然而,如果通過(guò)代碼示例去理解閉包,則簡(jiǎn)單很多。不過(guò),將閉包簡(jiǎn)單地看做局部變量,理解起來(lái)會(huì)更加簡(jiǎn)單。 - 譯者按: 在上一篇博客,我們通過(guò)實(shí)現(xiàn)一個(gè)計(jì)數(shù)器,了解了如何使用閉包(Closure),這篇博客將提供一些代碼示例,幫助大家理解閉包。 原文: JavaScript Clos...
摘要:但是閉包也不是什么復(fù)雜到不可理解的東西,簡(jiǎn)而言之,閉包就是閉包就是函數(shù)的局部變量集合,只是這些局部變量在函數(shù)返回后會(huì)繼續(xù)存在。可惜的是,并沒(méi)有提供相關(guān)的成員和方法來(lái)訪問(wèn)閉包中的局部變量。 (收藏自 技術(shù)狂) 前言:還是一篇入門文章。Javascript中有幾個(gè)非常重要的語(yǔ)言特性——對(duì)象、原型繼承、閉包。其中閉包 對(duì)于那些使用傳統(tǒng)靜態(tài)語(yǔ)言C/C++的程序員來(lái)說(shuō)是一個(gè)新的語(yǔ)言特性。本文將...
閱讀 720·2021-08-17 10:15
閱讀 1828·2021-07-30 14:57
閱讀 2049·2019-08-30 15:55
閱讀 2882·2019-08-30 15:55
閱讀 2762·2019-08-30 15:44
閱讀 733·2019-08-30 14:13
閱讀 2445·2019-08-30 13:55
閱讀 2648·2019-08-26 13:56