引言-----你知道嫦娥爲何那麼善變嗎??? 由於chang er啊,哈哈哈哈!前端
縱觀js,有三座大山,這三座大山分別爲--- 做用域/閉包 , 原型, 異步和單線程.難倒了一代又一代前端小白,小白髮揮着愚公移山的精神,撓碎多少頭髮。傷害了多少神經元。。。。。
今天我來講下我所理解的閉包。
es6
首先閉包產生地條件:有兩個。ajax
1.函數嵌套函數數組
2.變量在外面那個函數聲明,在裏面呢個函數調用。瀏覽器
給你們看一個例子安全
function foo(){
var a = 10;
return function(){
return ++a
}
}
var c = foo();
console.log(c());
console.log(c());複製代碼
這就是一個簡單的閉包,在瀏覽器調試器下能夠看到分別打印了 11 12;bash
(ps:謝謝熱心網友的矯正,錯誤已經改回來)閉包
那麼閉包有什麼做用呢?異步
做用1:保存即將要被銷燬的數據函數
舉個小栗子:
你們記得作tab選項卡是怎麼作的嗎?恩,對,應該不少人都會作,無非就是找按鈕的下標,找內容區域的下標,一一對應,for循環遍歷按鈕,點擊按鈕時,有事件了,因此產生了異步,for循環的i值不能對應到點擊事件的i值,這裏咱們取巧了,給每一個按鈕都添加了下標,對應下標的內容區域顯示出來,但是,存在一個問題,咱們要在按鈕組添加一個變量爲index,若是咱們不想要這個index,咱們能不能用其餘方法實現呢,答案是咱們能,能夠用es6的塊級做用域來實現,固然咱們也能夠用閉包來實現
如圖:一般實現tab選項卡的方法
利用閉包來實現
(function(){
var wrap = document.querySelector('#wrap');
var pic = document.querySelector('#wrap');
var aBtn = wrap.getElementsByTagName('li'); //獲取全部li組
var aPic = pic.getElementsByTagName('div'); //獲取全部div組
for(var i = 0;i<aBtn.length;i++){
!function(n){
aBtn[n].onclick = function(){
aBtn[n].style.display = 'block'
}
}(i)
}
}()複製代碼
是否是很神奇,就用了一個變量i。原本變量i for循環了就變成9(由於事件會產生異步);嘿嘿嘿嘿....利用閉包,巧妙了實現了i值得再次利用
做用2:保密
demo:寫一段js代碼,實現模擬汽車駕駛證科目一考試,作完一題,顯示出答案的效果
想必你們思路是有的,把答案全放進一個數組裏,數組的長度和題目的長度同樣,數組了存放正確答案,當用戶點擊按鈕時,在旁邊顯示的出此時此刻這個題目的答案,可是這樣數據不安全啊,稍微懂點代碼的人在控制檯輸出答案;怎麼作到數據的保密性呢,--閉包
!function(){
var aBtn = document.getElementsByClassName('btn');//獲取全部按鈕
var arr = ["A","B","C","A"...........] //存放答案數
for(var i = 0;i<aBtn.length;i++){
!function(n){
aBtn[n].onclick = function(){
console.log("正確答案是:"+arr[n])
}
}()
}複製代碼
就這樣寫出來了。利用匿名函數/立執行函數,數據不外泄,保密妥妥的,
其實說白了,閉包只是一種垃圾回收機制,有點像咱們電腦中的回收站同樣。變量聲明要被銷燬時,利用閉包能夠收集即將被銷燬的數據。
而後說下異步:上文也說起到了異步;咱們的js代碼是單線程執行的,從上到下執行;可是異步時候出現時。異步的執行代碼會讓同步的執行代碼有限經過;就比如紅綠燈同樣,等紅燈過去了咱們才能經過,異步就是這樣,等同步的代碼執行完了纔會經過,因此,同步老是優先於異步!
觸發異步的條件
___以上均爲本人原創,若有紕漏,望能矯正。