Javascript技巧之不要用for in语句对数组进行遍历

Javascript技巧之不要用for in语句对数组进行遍历

作者: 字体:[增加 减小] 类型:转载 时间:2010-10-20 我要评论

Javascript技巧-不要用for in语句对数组进行遍历的一些原因分析,需要的朋友可以参考下。
id="iframeu2261530_0" src="http://pos.baidu.com/acom?sz=680x200&rdid=2261530&dc=2&di=u2261530&dri=0&dis=0&dai=2&ps=403x5&coa=at%3D3%26rsi0%3D680%26rsi1%3D200%26pat%3D6%26tn%3DbaiduCustNativeAD%26rss1%3D%2523FFFFFF%26conBW%3D1%26adp%3D1%26ptt%3D0%26titFF%3D%2525E5%2525BE%2525AE%2525E8%2525BD%2525AF%2525E9%25259B%252585%2525E9%2525BB%252591%26titFS%3D14%26rss2%3D%2523000000%26titSU%3D0%26ptbg%3D90%26piw%3D0%26pih%3D0%26ptp%3D0&dcb=BAIDU_UNION_define&dtm=BAIDU_DUP_SETJSONADSLOT&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1456395895552&ti=Javascript%E6%8A%80%E5%B7%A7%E4%B9%8B%E4%B8%8D%E8%A6%81%E7%94%A8for%20in%E8%AF%AD%E5%8F%A5%E5%AF%B9%E6%95%B0%E7%BB%84%E8%BF%9B%E8%A1%8C%E9%81%8D%E5%8E%86_jquery_%E8%84%9A%E6%9C%AC%E4%B9%8B%E5%AE%B6&ari=1&dbv=2&drs=1&pcs=990x528&pss=1000x409&cfv=0&cpl=4&chi=1&cce=true&cec=GBK&tlm=1454005065&ltu=http%3A%2F%2Fwww.jb51.net%2Farticle%2F25036.htm&ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DiOsYCc4uSswgMOZi5TkaacBrSlMqk6Vd-qDDCWJw5MXGzHgTx_F1bM6zkxb9sDIz%26wd%3D%26eqid%3De98740070006541c0000000456ced62e&ecd=1&psr=1366x768&par=1366x728&pis=-1x-1&ccd=24&cja=false&cmi=6&col=zh-CN&cdo=-1&tcn=1456395896&qn=0159dc63d736cabc&tt=1456395895496.128.440.441" width="680" height="200" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="display: block; border-width: 0px; border-style: initial; vertical-align: bottom; margin: 0px;">
一,为什么不要用for in语句 

jqModal这个jquery插件估计很多人都使用过,在jqModal源码内部,有一个函数为hs,其中有个嵌套循环如下, 
复制代码代码如下:

for(var i in {jqmShow:1,jqmHide:1}) 
for(var s in this[i]) 
if(H[this[i][s]]) 
H[this[i][s]].w[i](this); 
return F; 


第一个for in遍历的目标是个匿名对象,没有问题。 
第二个for in遍历,根据上下文确认this[i]是一个数组对象(Array)。 
很多JS先驱者都告诫过我们不要对数组对象使用for in语句进行遍历,原因除了性能外,还有可能产生意料之内的bug。不听先人言,吃亏在眼前呵呵。 
今天偶拿jqModal为例,说明下这种bug到底什么时候会出现,当引以为戒。 
二,问题重现 
关键词:原生Array类、扩展Array类 
for in 语句对数组对象进行遍历潜在的bug在于:如果原生Array类被其他的js脚本库进行了原型扩展(比如多加一个toJSON方法即Array.prototype.toJSON=xxxx),那么用for in遍历扩展后的Array对象的逻辑将与遍历原生Array对象的逻辑发生差异。 
举个简单的例子, 

复制代码代码如下:

var x=[1]; 
for(var s in x){ 
alert(s); 
}; 

按常理,如果Array是原生js类,上面语句应该只执行一次alert方法,且s为数组的索引0。但是,如果Array类被扩展了,多了一个toJSON方法,那么上面的语句将执行两次alert,第一次s为索引0,第二次s为方法名'toJSON'。 

如果你设计的代码的逻辑以原生Array类为基准,在某一天你的同事在页面里面引用了一个第三方的JS库,这个库又恰好扩展了Array类,结果将难以想象,很有可能原来的代码逻辑将不再成立。 

关于这种扩展原生JS类的库,很有名的一个就是prototype.js,它给Array类扩展了很多方法诸如toJSON,each等等。我现在明白为啥jquery的创始人曾经对prototype火大了(不少人因为特殊原因在一个页面里用jquery同时又用prototype,会有很多意料之外的冲突问题,仅仅一个noConflict是无法解决的)。另外,jqModal的作者如果看得懂我这篇文章估计也会对埋怨prototype,说:“我用for in对数组遍历是不明智的,但是更该死的还是prototype。。。” 

如上所述,如果你在用jqModal,同时因为别的原因在用prototype,恭喜你中招了。冲突将导致jqModal的弹框在ie6、ie7下面将无法利用closeClass设置的按钮进行自动关闭。跟踪调试代码你将发现,异常的地方就在本文开头提到的hs方法的for in 循环中。。。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值