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 相关文章推荐
DWZ刷新dialog解决方法
Mar 03 Javascript
JavaScript实现动态创建CSS样式规则方案
Sep 06 Javascript
JavaScript中的Primitive对象封装介绍
Dec 31 Javascript
jquery中change()用法实例分析
Feb 06 Javascript
jQuery实现仿微软首页感应鼠标变化滑动窗口效果
Oct 08 Javascript
JS+JSP通过img标签调用实现静态页面访问次数统计的方法
Dec 14 Javascript
prototype与__proto__区别详细介绍
Jan 09 Javascript
JS出现失效的情况总结
Jan 20 Javascript
vue 和vue-touch 实现移动端左右导航效果(仿京东移动站导航)
Apr 22 Javascript
小程序实现列表删除功能
Oct 30 Javascript
vue单文件组件lint error自动fix与styleLint报错自动fix详解
Jan 08 Javascript
Vue简单实现原理详解
May 07 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 如何向 MySQL 发送数据
2006/10/09 PHP
PHP程序61条面向对象分析设计的经验小结
2008/11/12 PHP
ThinkPHP自动验证失败的解决方法
2011/06/09 PHP
PHP模型Model类封装数据库操作示例
2019/03/14 PHP
通过jQuery打造支持汉字,拼音,英文快速定位查询的超级select插件
2010/06/18 Javascript
jquery判断字符输入个数(数字英文长度记为1,中文记为2,超过长度自动截取)
2010/10/15 Javascript
将string解析为json的几种方式小结
2010/11/11 Javascript
JQuery 使用attr方法实现下拉列表选中
2014/10/13 Javascript
jQuery原生的动画效果
2015/07/10 Javascript
浅析2种JavaScript继承方式
2015/12/04 Javascript
封装好的javascript前端分页插件pagination
2016/01/04 Javascript
基于jQuery实现点击最后一行实现行自增效果的表格
2016/01/12 Javascript
理解javascript定时器中的setTimeout与setInterval
2016/02/23 Javascript
jQuery实现导航样式布局操作示例【可自定义样式布局】
2018/07/24 jQuery
Angularjs实现数组随机排序的方法
2018/10/02 Javascript
Nodejs实现多文件夹文件同步
2018/10/17 NodeJs
layui禁用侧边导航栏点击事件的解决方法
2019/09/25 Javascript
Javascript柯里化实现原理及作用解析
2020/10/22 Javascript
[原创]教女朋友学Python(一)运行环境搭建
2017/11/29 Python
python OpenCV学习笔记之绘制直方图的方法
2018/02/08 Python
使用python实现BLAST
2018/02/12 Python
python中利用matplotlib读取灰度图的例子
2019/12/07 Python
Python实现大数据收集至excel的思路详解
2020/01/03 Python
Python导入数值型Excel数据并生成矩阵操作
2020/06/09 Python
css3隔行变换色实现示例
2014/02/19 HTML / CSS
基于canvas使用贝塞尔曲线平滑拟合折线段的方法
2018/01/10 HTML / CSS
欧洲、亚洲、非洲和拉丁美洲的度假套餐:Great Value Vacations
2019/03/30 全球购物
十八大闭幕感言
2014/01/22 职场文书
简历中的自我评价怎么写
2014/01/29 职场文书
幼儿园儿童节主持词
2014/03/21 职场文书
尊老爱幼演讲稿
2014/09/04 职场文书
党员四风问题对照检查材料思想汇报
2014/09/16 职场文书
学校领导干部民主生活会整改方案
2014/09/29 职场文书
中学生综合素质自我评价
2015/03/06 职场文书
学校党支部公开承诺书
2015/04/30 职场文书
阿里云服务器部署mongodb的详细过程
2021/09/04 MongoDB