今天在面試的時候被問到閉包,自己我的感受仍是挺懂的,一時半會忽然又懵逼不知道從何提及(WTF). 好吧那我接下來在從新記錄下吧:git
其餘時效優質文章,歡迎查閱github
在計算機中,閉包指引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在。
侷限自定義: 在Javascript 中子函數中使用了其父函數或者外層函數的變量等就產生了一個閉包。這時外層變量的值能被子函數使用且外層變量在子函數未銷燬以前一直被分配不會被釋放。面試
閉包的產生因爲變量做用域鏈引發的(由詞法做用域致使)。
微信
在ES5及以前的語言規範中做用域分3種:閉包
[注意:沒有塊級做用域]函數
在函數中定義的變量,就屬於局部做用域,且只對函數範圍內其餘表達式可見。
而函數內部又可使用父函數中的變量這就是因爲做用域鏈,當JavaScript查找與變量關聯的值時,會遵循一個查找鏈。這個鏈是基於做用域的層次結構。 以下代碼:spa
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。code
值得注意的是:對象
清楚做用域的含義了嗎???索引
那麼咱們剛剛說的「詞法「做用域又是什麼。
其實詞法就是指代環境:因爲函數決定做用域,而且函數是一等公民能夠直接用來參數傳遞等。那麼做用域鏈是怎樣來肯定的呢: 下面的話背熟了:
做用域鏈是根據函數定義時候的位置肯定的而不是在調用時。--這就是「詞法」做用域
若是你還不懂閉包我TM。。。
最後咱們來看看幾個老生長談的基本栗子:
var liListlength = 3; for(var i=0;i<liListlength;i++){ var ele=document.querySelectorAll(".test > li")[i]; ele.addEventListener("click",function(){ alert("index is :" + i); }) } var liListlength = 3; for(var i=0;i<liListlength;i++){ var ele=document.querySelectorAll(".test > 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
此時咱們只暴露出了方法名而沒有暴露出變量屬性,這時要對變量的修改只有經過接口方法調用。
若有任何問題和建議歡迎發送至郵箱討論:<Tommy.White.h.li@gmail.com>
編寫不易,若您以爲對您有幫助,歡迎打賞
微信:
支付寶: