摘要:說源頭說起閉包的產生由于變量作用域鏈引起的由詞法作用域導致。閉包其實就是個稱呼,重要的是在這種場景下內部函數可以調用外部函數的變量,而這正是因為詞法作用域鏈。當閉包產生,在局部函數未被釋放之前,被引用外部函數的變量就無法被釋放。
今天在面試的時候被問到閉包,本身個人感覺還是挺懂的,一時半會突然又懵逼不知道從何說起(WTF). 好吧那我接下來在重新記錄下吧:
其他時效優質文章,歡迎查閱
專業名詞解釋:在計算機中,閉包指引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在。
局限自定義: 在Javascript 中子函數中使用了其父函數或者外層函數的變量等就產生了一個閉包。這時外層變量的值能被子函數使用且外層變量在子函數未銷毀之前一直被分配不會被釋放。
說源頭說起:閉包的產生由于變量作用域鏈引起的(由詞法作用域導致)。
?
在ES5及之前的語言規范中作用域分3種:
全局作用域
局部(函數作用域)
eval作用域。
[注意:沒有塊級作用域]
在函數中定義的變量,就屬于局部作用域,且只對函數范圍內其他表達式可見。
而函數內部又可以使用父函數中的變量這就是由于作用域鏈,當JavaScript查找與變量關聯的值時,會遵循一個查找鏈。這個鏈是基于作用域的層次結構。 如下代碼:
var a = "global variable"; ( function () { console.log(a); var fn = function () { var a = "local variable" console.log(a); } fn(); })() //輸出 //global variable //local variable
我們在window全局對象下聲明了變量a,隨后調用了一個立即執行函數,其中向控制臺直接打印變量a,由于立即執行函數沒有聲明局部變量a所以導致JavaScript向其作用域鏈繼續查找接著就在window對象中找到a變量并打印出它的值"global variable"。接著這個立即執行函數聲明了一個局部函數變量再調用它,在這個函數變量中首先聲明了一個局部變量a然后在向控制臺輸出a得值。JavaScript在執行時由于在fn函數作用域內部查找到了變量a就直接使用變量a的值所以打印出了local variable。
值得注意的是:
這里其實有2個閉包環境一個是window對象和立即執行函數所創建的閉包;另一個是立即執行函數和其內部聲明的函數變量fn創建的閉包。
閉包其實就是個稱呼,重要的是在這種場景下內部函數可以調用外部函數的變量,而這正是因為詞法作用域鏈。
當閉包產生,在局部函數未被釋放之前,被引用外部函數的變量就無法被釋放。
清楚作用域的含義了嗎???
那么我們剛剛說的“詞法“作用域又是什么。
其實詞法就是指代環境:由于函數決定作用域,并且函數是一等公民可以直接用來參數傳遞等。那么作用域鏈是怎樣來確定的呢: 下面的話背熟了:
作用域鏈是根據函數定義時候的位置確定的而不是在調用時。--這就是“詞法”作用域
如果你還不懂閉包我TM。。。
最后我們來看看幾個老生長談的基本栗子:
[閉包的影響]對一些li綁定點擊事件并打印其索引,對比2斷代碼不解釋:
var liListlength = 3; for(var i=0;ili")[i]; ele.addEventListener("click",function(){ alert("index is :" + i); }) } var liListlength = 3; for(var i=0;i li")[i]; ele.addEventListener("click",(function(i){ return function(){ alert("index is :" + i); } })(i)) }
[閉包的妙用]模擬封裝
我們可以運用閉包模擬模塊的實現,即我們可以只暴露方法接口隱藏局部變量,具體如下:
var countMoudle = (function(){ var _count = 0; var plus = function(){ ? _count++; }; var minus = function(){ ? _count--; }; var print = function(){ console.log(_count); } return { ? plus: plus, ? minus: minus, ? print: print }; })(); countMoudle.print() //0 countMoudle.plus() countMoudle.print() //1 countMoudle.minus() countMoudle.print() //0
此時我們只暴露出了方法名而沒有暴露出變量屬性,這時要對變量的修改只有通過接口方法調用。
最后如有任何問題和建議歡迎發送至郵箱討論:
編寫不易,若您覺得對您有幫助,歡迎打賞
微信:
支付寶:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/95367.html
語法 for ([initialization]; [condition]; [final-expression]) { statement } initialization一個表達式 (包含賦值語句) 或者變量聲明。典型地被用于初始化一個計數器。該表達式可以使用var或let關鍵字聲明新的變量,使用var聲明的變量不是該循環的局部變量,而是與for循環處在同樣的作用域中。用let聲明的...
摘要:委托上面的代碼結合了構造函數和原型兩種方式去創建對象,首先聊聊構造函數構造函數構造函數本質上還是函數,只不過為了區分將其首字母大寫了而已。注意注釋掉的代碼是自動執行的,但這并不是構造函數獨有的,每個函數在聲明時都會自動生成。 首先看看下面兩個1+1=2的問題: 問題一:為什么改變length的值,數組的內容會變化? var arr = [1]; arr.length = 3; aler...
摘要:聲明的變量不得改變值,這意味著,一旦聲明變量,就必須立即初始化,不能留到以后賦值。 雖然今年沒有換工作的打算 但為了跟上時代的腳步 還是忍不住整理了一份最新前端知識點 知識點匯總 1.HTML HTML5新特性,語義化瀏覽器的標準模式和怪異模式xhtml和html的區別使用data-的好處meta標簽canvasHTML廢棄的標簽IE6 bug,和一些定位寫法css js放置位置和原因...
摘要:聲明的變量不得改變值,這意味著,一旦聲明變量,就必須立即初始化,不能留到以后賦值。 雖然今年沒有換工作的打算 但為了跟上時代的腳步 還是忍不住整理了一份最新前端知識點 知識點匯總 1.HTML HTML5新特性,語義化瀏覽器的標準模式和怪異模式xhtml和html的區別使用data-的好處meta標簽canvasHTML廢棄的標簽IE6 bug,和一些定位寫法css js放置位置和原因...
閱讀 2538·2021-07-26 23:38
閱讀 3438·2019-08-30 13:10
閱讀 2324·2019-08-29 18:33
閱讀 2326·2019-08-29 16:12
閱讀 993·2019-08-29 10:59
閱讀 1803·2019-08-26 17:40
閱讀 775·2019-08-26 11:59
閱讀 818·2019-08-26 11:41