把複雜的知識簡單化------------------------------------------westlife
引言-----你知道嫦娥為什麼那麼善變嗎??? 因為chang er啊,哈哈哈哈!
縱觀js,有三座大山,這三座大山分別為--- 作用域/閉包 , 原型, 非同步和單執行緒.難倒了一代又一代前端小白,小白髮揮著愚公移山的精神,撓碎多少頭髮。傷害了多少神經元。。。。。
今天我來說下我所理解的閉包。
首先閉包產生地條件:有兩個。
1.函式巢狀函式
2.變數在外面那個函式宣告,在裡面呢個函式呼叫。
給大家看一個例子
function foo(){
var a = 10;
return function(){
return ++a
}
}
var c = foo();
console.log(c());
console.log(c());複製程式碼
這就是一個簡單的閉包,在瀏覽器偵錯程式下可以看到分別列印了 11 12;
(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程式碼是單執行緒執行的,從上到下執行;但是非同步時候出現時。非同步的執行程式碼會讓同步的執行程式碼有限通過;就好比紅綠燈一樣,等紅燈過去了我們才能通過,非同步就是這樣,等同步的程式碼執行完了才會通過,所以,同步總是優先於非同步!
觸發非同步的條件
- ajax
- 事件
- setTimeout() setInterval()
___以上均為本人原創,如有紕漏,望能矯正。