JavaScript 閉包詳細介紹
深入理解JavaScript——閉包
跟很多新手一樣我也是初入前端,對閉包的理解花費的時間和精力相當?shù)亩?。效果也還行,今天我就來根據(jù)自己的理解細致的講一講閉包,由于是初入學習的時候不免有一些彎路和困惑,我想信這也是很多跟我一樣的人會同樣遇到的問題。我就以自己的學習路徑和遇到的各種坑來談閉包。希望對各位有一定的幫助。(菜鳥,也請各位多多指教)
閉包是什么?《JavaScript高級程序設計》上面這么描述的:閉包是指有權訪問另一個函數(shù)作用域中的變量的函數(shù)。這句話第一次看的時候模模糊糊,似是而非。碰到問題就不會運用了,聽別人的分析頭頭是道,說到底還是沒搞明白。現(xiàn)在我覺得要徹底搞清這句話必須對JavaScript的作用域,匿名函數(shù),甚至JavaScript的編譯原理有一些簡單的了解。經(jīng)過查閱理解各種資料書籍對閉包的解釋,再回過頭來看了一些源碼,慢慢的有了一點感覺。我覺得對閉包描述最好的一句話是:“閉包是基于詞法作用域書寫代碼時所產(chǎn)生的自然結果,你甚至不需要為了利用它而有意為之的創(chuàng)建閉包,閉包的創(chuàng)建和使用是在你的代碼中隨處可見。你缺少的是根據(jù)你自己的意愿來識別,擁抱和影響閉包的思維環(huán)境?!痹捰悬c長但點出來閉包在JavaScript這么語言中存在的實際價值,大家可以細細體會一下。接下來我已實際例子來講講閉包。
首先看一個簡單的例子:
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; } } }
例子中返回的是一個匿名函數(shù),其中匿名函數(shù)中value1,value2同時又對外部函數(shù)createComparisonFunction()的參數(shù)propertyName進行調用。再看看上面對閉包的定義:有權訪問另一個函數(shù)作用域中的變量的函數(shù)。return的匿名函數(shù)有權訪問外部函數(shù)作用域中的變量propertyName,因此這是一個閉包。但實際來說這只是一個基于詞法作用域的查找規(guī)則,很好理解也很自然。
可能有些人不明白什么是詞法作用域的查找規(guī)則:其實說簡單點就是根據(jù)變量的作用鏈域來查找并取得該變量。以上例來說:createComparisonFunction函數(shù)的作用域包含一個變量property和一個匿名函數(shù)(由于沒有函數(shù)名其實在createComparisonFunction函數(shù)中也無法調用,這也是匿名函數(shù)的一個缺點,記得事件監(jiān)聽函數(shù)調用一個匿名函數(shù)時是無法移除嗎?道理是一樣的),匿名函數(shù)作用域中包括obj1,obj2,value1,value2這四個變量。匿名函數(shù)中的變量調用時首先在自己作用域中查詢,找到了該變量就調用,找不到就往外層走接著找,直到全局作用域如果還是找不到就會報ReferenceError(如果找到了一個var a;呢?由于a為undefined所以會報TypeError)。而createComparisonFunction函數(shù)則只能在他的作用域中查找,不能去內(nèi)層的匿名函數(shù)中查找,這種查找規(guī)則就是詞法作用域的查找規(guī)則(當然這不只是基本規(guī)則)。
我們再來看一個例子:
function foo() { var a = 2; function bar() { console.log( a ); } return bar; } var baz = foo(); baz(); //2
答案可能很多人都能猜出來但其實現(xiàn)原理是怎樣呢?我現(xiàn)在就來細致的分析一下:首先聲明了一個函數(shù)foo其作用域包括變量a和bar函數(shù)。foo函數(shù)內(nèi)部有一個函數(shù)bar內(nèi)部沒有新變量。然后定義一個變量baz,其值為foo()而foo()返回bar,顧baz=bar;最后一句baz()即等價于bar();根據(jù)詞法作用域的規(guī)則bar是在foo函數(shù)中聲明的。外部是無法訪問的呀!這正是閉包的神奇之處!我們再一次回到閉包定義:有權訪問另一個函數(shù)作用域中的變量的函數(shù),baz()函數(shù)有權訪問foo函數(shù)中的bar。這就是閉包對吧!搞清閉包后有些人還會疑問?閉包是怎么形成的,為什么你說它有權訪問foo中的bar呢?首先閉包的形成是在一個函數(shù)內(nèi)部創(chuàng)建一個函數(shù)這是創(chuàng)建閉包的最常見方法。當將內(nèi)部函數(shù)傳遞到它的詞法作用域以外他都會持有對原始定義作用域的引用,執(zhí)行此函數(shù)就會 使用閉包。
閉包的基礎大概就是這幾點,希望大家能仔細體會。抽時間補充點閉包的一些其他用途,來幫大家擴展一下思維。
通過此文,希望大家對閉包的知識掌握,謝謝大家對本站的支持!
相關文章
JavaScript碎片—函數(shù)閉包(模擬面向對象)
這篇文章主要介紹了JavaScript函數(shù)閉包,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-03-03Javascript SHA-1:Secure Hash Algorithm
Javascript SHA-1:Secure Hash Algorithm...2006-12-12利用javascript數(shù)組長度循環(huán)數(shù)組內(nèi)所有元素
javascript循環(huán)數(shù)組內(nèi)所有元素代碼學習,大家參考使用吧2013-12-12