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 相关文章推荐
纯js实现的论坛常用的运行代码的效果
Jul 15 Javascript
JS替换字符串中字符即替换全部而不是第一个
Jun 04 Javascript
JavaScript 学习笔记之操作符
Jan 14 Javascript
13个PHP函数超实用
Oct 21 Javascript
基于Bootstrap重置输入框内容按钮插件
May 12 Javascript
JS控制静态页面之间传递参数获取参数并应用的简单实例
Aug 10 Javascript
jQuery 循环遍历改变a标签的href(实例讲解)
Jul 12 jQuery
动态创建Angular组件实现popup弹窗功能
Sep 15 Javascript
vue同步父子组件和异步父子组件的生命周期顺序问题
Oct 07 Javascript
JavaScript判断浏览器运行环境的详细方法
Jun 30 Javascript
微信小程序自定义波浪组件使用方法详解
Sep 21 Javascript
微信小程序 导入图标实现过程详解
Oct 11 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中的session永不过期的解决思路及实现方法分享
2011/04/20 PHP
获取用户Ip地址通用方法与常见安全隐患(HTTP_X_FORWARDED_FOR)
2013/06/01 PHP
php实现建立多层级目录的方法
2014/07/19 PHP
yii2分页之实现跳转到具体某页的实例代码
2016/06/02 PHP
php爬取天猫和淘宝商品数据
2018/02/23 PHP
JavaScript 设计模式学习 Factory
2009/07/29 Javascript
jquery-easyui关闭tab自动切换到前一个tab
2010/07/29 Javascript
js优化针对IE6.0起作用(详细整理)
2012/12/25 Javascript
Javascript实现关联数据(Linked Data)查询及注意细节
2013/02/22 Javascript
jquery退出each循环的写法
2014/02/26 Javascript
一个简单的jQuery计算器实现了连续计算功能
2014/07/21 Javascript
js显示当前日期时间和星期几
2015/10/22 Javascript
vue自定义指令实现v-tap插件
2016/11/03 Javascript
JavaScript中如何判断一个值的类型
2017/09/15 Javascript
jQuery ajax读取本地json文件的实例
2017/10/31 jQuery
JS实现的计数排序与基数排序算法示例
2017/12/04 Javascript
微信小程序使用picker实现时间和日期选择框功能【附源码下载】
2017/12/11 Javascript
vue左侧菜单,树形图递归实现代码
2018/08/24 Javascript
jQuery中each遍历的三种方法实例分析
2018/09/07 jQuery
浅谈Vue 性能优化之深挖数组
2018/12/11 Javascript
Node.js JSON模块用法实例分析
2019/01/04 Javascript
node.js获取参数的常用方法(总结)
2017/05/29 Python
python 字典修改键(key)的几种方法
2018/08/10 Python
Python实现个人微信号自动监控告警的示例
2019/07/03 Python
python抓取多种类型的页面方法实例
2019/11/20 Python
3分钟看懂Python后端必须知道的Django的信号机制
2020/07/26 Python
python中spy++的使用超详细教程
2021/01/29 Python
CSS3 media queries + jQuery实现响应式导航
2016/09/30 HTML / CSS
会计专业自荐信
2013/12/02 职场文书
前处理班长职位说明书
2014/03/01 职场文书
学习两会精神心得范文
2014/03/17 职场文书
初中作文评语大全
2014/04/23 职场文书
高中竞选班长演讲稿
2014/04/24 职场文书
学生不参加考试检讨书
2015/02/19 职场文书
实用求职信模板范文
2019/05/13 职场文书
OpenCV全景图像拼接的实现示例
2021/06/05 Python