需求:有一个数组,根据数组的值渲染对应的数字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); }