需求:有一個數組,根據數組的值渲染對應的數字div,單擊對應的div 在控制檯打印對應的數字。如點擊1,控制檯打印1.html
問題: 無論點擊哪一個值 打出來都是4數組
代碼以下瀏覽器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>testFor</title> </head> <body> <div id="container"> </div> <script> var arr=[1,2,3,4]; function clickNum(i) { console.log(i) } for(var i of arr){ var iDiv=document.createElement('div'); iDiv.addEventListener('click',function () { clickNum(i) }); iDiv.innerText=i; var container=document.getElementById('container'); container.appendChild(iDiv); } </script> </body> </html>
指望點擊會打印出對應的數字,實際打出來的都是4閉包
緣由:app
js函數在聲明時,瀏覽器不會去查看函數內部邏輯。只有函數被使用時 才關心函數內部的變量引用。函數
如本例,只有在單擊的時候 纔會去觸發clickNum函數,而此時循環已執行完畢,i已經變成了4。 因此無論哪一個div的click 事件打印出來永遠都是4。spa
解決思路:code
1.由於咱們須要用到即時的索引值i.因此 咱們須要當即觸發此函數。這裏須要用到匿名函數。htm
2.有了匿名函數當即執行後,咱們還須要將匿名函數中的變量暫存起來,留着點擊的時候用,這裏須要建立一個閉包。由於閉包的本質就是讓內部的變量在函數執行完後也不被垃圾回收調。而是暫存起來。因此,若是須要在函數外部拿到函數內部的變量。或者想在未來拿到如今的變量 都只能經過閉包(我我的理解是這樣的)blog
改後的代碼
for(var i of arr){ var iDiv=document.createElement('div'); iDiv.addEventListener('click',function (icopy) { return function () { clickNum(icopy) } }(i)); iDiv.innerText=i; var container=document.getElementById('container'); container.appendChild(iDiv); }