註意:這篇文章最初發表在我自己折騰的博客站點上:javascript閉包的使用--按鈕切換,該博客用了一位前輩開源的源碼,基於thinkjs和vuejs開發,歡迎大家來逛逛。 閉包實現按鈕狀態切換看下麵的代碼: 解釋上面的代碼實現了點擊按鈕切換樣式的功能,它用到了js的閉包特性。簡單解釋下:togg ...
閉包實現按鈕狀態切換
看下麵的代碼:
1 var toggleBtn = document.getElementById('toggle'); 2 3 var toggleFun = (function() { 4 var checked = true; 5 6 return function() { 7 var color = checked ? 'red' : 'white'; 8 toggleBtn.style.backgroundColor = color; 9 checked = !checked; 10 }; 11 })(); 12 13 // 切換按鈕 14 toggleBtn.addEventListener('click', toggleFun);
解釋
上面的代碼實現了點擊按鈕切換樣式的功能,它用到了js的閉包特性。簡單解釋下:
toggleFun為一個立即執行函數,執行後toggleFun被賦值為內部函數:
1 toggleFun = function() { 2 color = checked ? 'red' : 'white'; 3 toggleBtn.style.backgroundColor = color; 4 checked = !checked; 5 }
這個函數用到了外部函數的checked變數,這也是checked變數在立即執行函數執行完成後未被銷毀的原因,因為還有其他地方用到了它。那麼這個內部函數被用作事件監聽器的回調函數,每點擊一次就會被調用一次,從而可以通過更改checked的值來實現按鈕切換效果。立即執行函數內的函數被全局下的toggleFun變數引用了,這就創建了一個閉包。
簡而言之,閉包的作用就是在立即執行函數執行完並返回後,使得javascript的垃圾回收機制不會收回立即函數所占用的資源,因為立即執行函數的內部函數依賴立即執行函數中的變數。
額,上面寫的太啰嗦了,下麵把代碼稍微改下,加些註釋就會更加清晰:
1 var toggleBtn = document.getElementById('toggle'); 2 3 var outerFun = function() { 4 var checked = true; 5 6 // innerFun聲明時用到了outerFun的局部變數 7 var innerFun = function() { 8 var color = checked ? 'red' : 'white'; 9 toggleBtn.style.backgroundColor = color; 10 checked = !checked; 11 }; 12 13 return innerFun; 14 }; 15 16 var toggleFun = outerFun(); // toggleFun指向innerFun 17 18 // 切換按鈕,每次點擊都會調用innerFun 19 toggleBtn.addEventListener('click', toggleFun);
不用閉包,用全局變數
其實不用閉包也能實現按鈕切換,不過就得用到全局變數來存儲按鈕狀態:
1 var toggleBtn = document.getElementById('toggle'); 2 var checked = true; // 全局變數存儲按鈕狀態 3 4 var toggleFun = function() { 5 var color = checked ? 'red' : 'white'; 6 toggleBtn.style.backgroundColor = color; 7 checked = !checked; 8 }; 9 10 toggleBtn.addEventListener('click', toggleFun);
但全局變數用多了會不好維護,代碼不好控制。
這篇文章最初發表在我自己折騰的博客站點上:javascript閉包的使用--按鈕切換,該博客用了一位前輩開源的源碼,基於thinkjs和vuejs開發,歡迎大家來逛逛。