深入理解JavaScript——閉包
跟很多新手一樣我也是初入前端,對(duì)閉包的理解花費(fèi)的時(shí)間和精力相當(dāng)?shù)亩?。效果也還行,今天我就來根據(jù)自己的理解細(xì)致的講一講閉包,由于是初入學(xué)習(xí)的時(shí)候不免有一些彎路和困惑,我想信這也是很多跟我一樣的人會(huì)同樣遇到的問題。我就以自己的學(xué)習(xí)路徑和遇到的各種坑來談閉包。希望對(duì)各位有一定的幫助。(菜鳥,也請(qǐng)各位多多指教)
閉包是什么?《JavaScript高級(jí)程序設(shè)計(jì)》上面這么描述的:閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。這句話第一次看的時(shí)候模模糊糊,似是而非。碰到問題就不會(huì)運(yùn)用了,聽別人的分析頭頭是道,說到底還是沒搞明白?,F(xiàn)在我覺得要徹底搞清這句話必須對(duì)JavaScript的作用域,匿名函數(shù),甚至JavaScript的編譯原理有一些簡(jiǎn)單的了解。經(jīng)過查閱理解各種資料書籍對(duì)閉包的解釋,再回過頭來看了一些源碼,慢慢的有了一點(diǎn)感覺。我覺得對(duì)閉包描述最好的一句話是:“閉包是基于詞法作用域書寫代碼時(shí)所產(chǎn)生的自然結(jié)果,你甚至不需要為了利用它而有意為之的創(chuàng)建閉包,閉包的創(chuàng)建和使用是在你的代碼中隨處可見。你缺少的是根據(jù)你自己的意愿來識(shí)別,擁抱和影響閉包的思維環(huán)境?!痹捰悬c(diǎn)長(zhǎng)但點(diǎn)出來閉包在JavaScript這么語言中存在的實(shí)際價(jià)值,大家可以細(xì)細(xì)體會(huì)一下。接下來我已實(shí)際例子來講講閉包。
首先看一個(gè)簡(jiǎn)單的例子:
function createComparisonFunction(propertyName){ return function(obj1,obj2){ var value1=object1[propertyName]; var value2=object2[propertyName]; if(value1<value2){ return -1; }else if(value1>value2){ return 1; }else{ return 0; } } }例子中返回的是一個(gè)匿名函數(shù),其中匿名函數(shù)中value1,value2同時(shí)又對(duì)外部函數(shù)createComparisonFunction()的參數(shù)propertyName進(jìn)行調(diào)用。再看看上面對(duì)閉包的定義:有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。return的匿名函數(shù)有權(quán)訪問外部函數(shù)作用域中的變量propertyName,因此這是一個(gè)閉包。但實(shí)際來說這只是一個(gè)基于詞法作用域的查找規(guī)則,很好理解也很自然。
可能有些人不明白什么是詞法作用域的查找規(guī)則:其實(shí)說簡(jiǎn)單點(diǎn)就是根據(jù)變量的作用鏈域來查找并取得該變量。以上例來說:createComparisonFunction函數(shù)的作用域包含一個(gè)變量property和一個(gè)匿名函數(shù)(由于沒有函數(shù)名其實(shí)在createComparisonFunction函數(shù)中也無法調(diào)用,這也是匿名函數(shù)的一個(gè)缺點(diǎn),記得事件監(jiān)聽函數(shù)調(diào)用一個(gè)匿名函數(shù)時(shí)是無法移除嗎?道理是一樣的),匿名函數(shù)作用域中包括obj1,obj2,value1,value2這四個(gè)變量。匿名函數(shù)中的變量調(diào)用時(shí)首先在自己作用域中查詢,找到了該變量就調(diào)用,找不到就往外層走接著找,直到全局作用域如果還是找不到就會(huì)報(bào)ReferenceError(如果找到了一個(gè)var a;呢?由于a為undefined所以會(huì)報(bào)TypeError)。而createComparisonFunction函數(shù)則只能在他的作用域中查找,不能去內(nèi)層的匿名函數(shù)中查找,這種查找規(guī)則就是詞法作用域的查找規(guī)則(當(dāng)然這不只是基本規(guī)則)。
新聞熱點(diǎn)
疑難解答
圖片精選