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