关于for循环中的闭包问题
还是昨天的那个简单的小项目,已经花了一天的时间了 - - 。从&&的用法,到CSStext,到今天马上要谈的闭包(closure),通过一个小东西,真真发现了自己的各方面不足。昨天发完源码之后,自己手写一遍,还是碰到了一些问题,最主要的就是for循环中的闭包问题。
这是我之前的代码,大致就是这样:
for(var i = 0;i<=oBtn.length;i++){ oBtn[i].onclick=function(){ change_style(oDiv,oAttr[i],oVal[i]); } }
当时理所应当会以为出来结果,才发现虽然没有报错,但是也没有反应。console了一下发现oAttr[i],oVal[i],都是undefined,这就让我纳闷了,然后测试了一个例子:
for(var i = 0;i<=5;i++){ input.onclick=function(){ console.log(i); } }
测试结果为一个6让我蛋疼了好一会 - -,然后在网上google了之后发现,问题的原因大致是当for循环执行完毕后,i变量被垃圾回收,接着执行click函数的时候,因为内部没有i变量所以会去父级作用域去找,那时for循环已经执行完成,所以只会输出6.我自己的理解的话,解决方法总结起来应该是两种类型,一种就是增加若干个对应的闭包域空间(这里采用的是匿名函数),专门用来存储原先需要引用的内容(下标),不过只限于基本类型(基本类型值传递,对象类型引用传递),另一种就是用一个变量索引,保存一直i的值。
还是拿上一篇的例子,实现简单的DIV属性切换,如果用闭包实现的话可以这样:
for(var i=0;i<=oBtn.length-1;i++){ (function(i){ oBtn[i].onclick=function(){ if (i == 4) { oDiv.style.cssText = ''; }else{ change_style(oDiv,oAttr[i],oVal[i]); } } })(i) }
如果不用闭包的话用索引缓存就可以参考上一篇文章的写法。
感谢阅读!