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 替换
Feb 19 Javascript
jQuery控制图片的hover效果(smartRollover.js)
Mar 18 Javascript
jquery验证手机号码、邮箱格式是否正确示例代码
Jul 28 Javascript
JavaScript调用浏览器打印功能实例分析
Jul 17 Javascript
基于JavaScript实现百叶窗动画效果不只单纯flas可以实现
Feb 29 Javascript
JS使用单链表统计英语单词出现次数
Jun 16 Javascript
自己封装的一个原生JS拖动方法(推荐)
Nov 22 Javascript
jquery编写日期选择器
Mar 16 Javascript
微信小程序学习笔记之表单提交与PHP后台数据交互处理图文详解
Mar 28 Javascript
ES6基础之数组和对象的拓展实例详解
Aug 22 Javascript
JS简易计算器实例讲解
Jun 30 Javascript
如何手写简易的 Vue Router
Oct 10 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/09/06 PHP
19个超实用的PHP代码片段
2014/03/14 PHP
php编程每天必学之验证码
2016/03/03 PHP
Yii2学习笔记之汉化yii设置表单的描述(属性标签attributeLabels)
2017/02/07 PHP
ThinkPHP中类的构造函数_construct()与_initialize()的区别详解
2017/03/13 PHP
PHP设计模式之数据访问对象模式(DAO)原理与用法实例分析
2019/12/12 PHP
Jquery+WebService 校验账号是否已被注册的代码
2010/07/12 Javascript
ASP.NET jQuery 实例9  通过控件hyperlink实现返回顶部效果
2012/02/03 Javascript
原生JS绑定滑轮滚动事件兼容常见浏览器
2014/06/30 Javascript
JavaScript使用ActiveXObject访问Access和SQL Server数据库
2015/04/02 Javascript
jQuery获取父元素及父节点的方法小结
2016/04/14 Javascript
AngularJS指令详解及示例代码
2016/08/16 Javascript
javascript实现多张图片左右无缝滚动效果
2017/03/22 Javascript
jQuery实现选中行变色效果(实例讲解)
2017/07/06 jQuery
浅析Javascript中双等号(==)隐性转换机制
2017/10/27 Javascript
Vue-Router模式和钩子的用法
2018/02/28 Javascript
IE9 elementUI文件上传的问题解决
2018/10/17 Javascript
vue-cli3.0实现一个多页面应用的历奇经历记录总结
2020/03/16 Javascript
js+canvas实现图片格式webp/png/jpeg在线转换
2020/08/22 Javascript
python使用clear方法清除字典内全部数据实例
2015/07/11 Python
Python字典的核心底层原理讲解
2019/01/24 Python
Python I/O与进程的详细讲解
2019/03/08 Python
Python下应用opencv 实现人脸检测功能
2019/10/24 Python
Python实现SMTP邮件发送
2020/06/16 Python
python实现图像外边界跟踪操作
2020/07/13 Python
使用CSS3实现input多选框自定义样式的方法示例
2019/07/19 HTML / CSS
耐克巴西官方网站:Nike巴西
2016/08/14 全球购物
英国假睫毛购买网站:FalseEyelashes.co.uk
2018/05/23 全球购物
Pretty You London官网:英国拖鞋和睡衣品牌
2019/05/08 全球购物
社会实践自我鉴定
2013/11/07 职场文书
教师业务学习制度
2014/01/25 职场文书
舞蹈毕业生的自我评价
2014/03/05 职场文书
文秘自荐信
2014/06/28 职场文书
甜美蛋糕店的创业计划书模板,拿来即用!
2019/08/21 职场文书
python使用pygame创建精灵Sprite
2021/04/06 Python
golang中的struct操作
2021/11/11 Golang