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


Posted in Javascript onOctober 20, 2010

一,为什么不要用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 循环中。。。
三,解决问题
遍历数组的地方,用for var 语句代替for in。

Javascript 相关文章推荐
jquery 注意事项与常用语法小结
Jun 07 Javascript
jQuery 自定义函数写法分享
Mar 30 Javascript
网页运行时提示对象不支持abigimage属性或方法
Aug 10 Javascript
Javascript中封装window.open解决不兼容问题
Sep 28 Javascript
javascript每日必学之运算符
Feb 16 Javascript
深入浅析JavaScript中的constructor
Apr 19 Javascript
js删除Array数组中指定元素的两种方法
Aug 03 Javascript
浅谈jQuery中事情的动态绑定
Feb 12 Javascript
JS实现的点击表头排序功能示例
Mar 27 Javascript
JavaScript伪数组用法实例分析
Dec 22 Javascript
JS中的算法与数据结构之队列(Queue)实例详解
Aug 20 Javascript
Nest.js散列与加密实例详解
Feb 24 Javascript
来自国外的14个图片放大编辑的jQuery插件整理
Oct 20 #Javascript
理解Javascript_12_执行模型浅析
Oct 18 #Javascript
理解Javascript_11_constructor实现原理
Oct 18 #Javascript
关于js中window.location.href,location.href,parent.location.href,top.location.href的用法与区别
Oct 18 #Javascript
jQuery Validation实例代码 让验证变得如此容易
Oct 18 #Javascript
jQuery 验证插件 Web前端设计模式(asp.net)
Oct 17 #Javascript
基本jquery的控制tabs打开的数量的代码
Oct 17 #Javascript
You might like
PHP采集腾讯微博的实现代码
2012/01/19 PHP
destoon实现不同会员组公司名称显示不同的颜色的方法
2014/08/22 PHP
盘点PHP和ASP.NET的10大对比!
2015/12/24 PHP
php Session无效分析资料整理
2016/11/29 PHP
My Desktop :) 桌面式代码
2008/12/29 Javascript
IE事件对象(The Internet Explorer Event Object)
2012/06/27 Javascript
jQuery常用数据处理方法小结
2015/02/20 Javascript
js实现tab切换效果实例
2015/09/16 Javascript
AngularJS实现元素显示和隐藏的几个案例
2015/12/09 Javascript
省市二级联动小案例讲解
2016/07/24 Javascript
聊一聊JS中的prototype
2016/09/29 Javascript
jQuery Dialog 打开时自动聚焦的解决方法(两种方法)
2016/11/24 Javascript
canvas 画布在主流浏览器中的尺寸限制详细介绍
2016/12/15 Javascript
JS中定位 position 的使用实例代码
2017/08/06 Javascript
在vue中,v-for的索引index在html中的使用方法
2018/03/06 Javascript
node基于puppeteer模拟登录抓取页面的实现
2018/05/09 Javascript
Vue指令v-for遍历输出JavaScript数组及json对象的常见方式小结
2019/02/11 Javascript
Vue项目中使用better-scroll实现菜单映射功能方法
2019/09/11 Javascript
Vue 实现创建全局组件,并且使用Vue.use() 载入方式
2020/08/11 Javascript
JavaScript实现拖拽和缩放效果
2020/08/24 Javascript
Python获取DLL和EXE文件版本号的方法
2015/03/10 Python
Python制作豆瓣图片的爬虫
2017/12/28 Python
python在html中插入简单的代码并加上时间戳的方法
2018/10/16 Python
Django Rest framework之认证的实现代码
2018/12/17 Python
Python合并2个字典成1个新字典的方法(9种)
2019/12/19 Python
关于keras中keras.layers.merge的用法说明
2020/05/23 Python
python 发送get请求接口详解
2020/11/17 Python
YOOX美国官方网站:全球著名的多品牌时尚网络概念店
2016/09/11 全球购物
ALLSAINTS英国官网:伦敦新锐潮流品牌
2016/09/19 全球购物
俄罗斯旅游网站:Tripadvisor俄罗斯
2017/03/21 全球购物
Abbacino官网:包、钱包和女士配饰
2019/04/15 全球购物
2014年秋季新学期寄语
2014/08/02 职场文书
财务审计整改报告
2014/11/06 职场文书
护士先进个人总结
2015/02/13 职场文书
现役军人家属慰问信
2015/03/24 职场文书
校长一岗双责责任书
2015/05/09 职场文书