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 相关文章推荐
div+css布局的图片连续滚动js实现代码
May 04 Javascript
在jQuery1.5中使用deferred对象 着放大镜看Promise
Mar 12 Javascript
AngularJS + Node.js + MongoDB开发的基于高德地图位置的通讯录
Jan 02 Javascript
使用npm发布Node.JS程序包教程
Mar 02 Javascript
动态加载js文件简单示例
Apr 21 Javascript
jQuery树形控件zTree使用小结
Aug 02 Javascript
JavaScript“尽快失败”的原则实例详解
Oct 08 Javascript
JAVA中截取字符串substring用法详解
Apr 14 Javascript
详解基于Angular4+ server render(服务端渲染)开发教程
Aug 28 Javascript
vue双花括号的使用方法 附练习题
Nov 07 Javascript
vue缓存的keepalive页面刷新数据的方法
Apr 23 Javascript
详解从vue-loader源码分析CSS Scoped的实现
Sep 23 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 microtime获取浮点的时间戳
2010/02/21 PHP
php实现仿写CodeIgniter的购物车类
2015/07/29 PHP
浅析javascript闭包 实例分析
2010/12/25 Javascript
日期处理的js库(迷你版)--自建js库总结
2011/11/21 Javascript
国外大牛IE版本检测!现在IE都到9了,IE检测代码
2012/01/04 Javascript
输入自动提示搜索提示功能的javascript:sugggestion.js
2013/09/02 Javascript
禁止IE用右键的JS代码
2013/12/30 Javascript
Js判断CSS文件加载完毕的具体实现
2014/01/17 Javascript
input输入密码变黑点密文的实现方法
2017/01/09 Javascript
常用jQuery选择器汇总
2017/02/02 Javascript
微信小程序左滑删除效果的实现代码
2017/02/20 Javascript
BootStrap 动态表单效果
2017/06/02 Javascript
浅谈Vue Element中Select下拉框选取值的问题
2018/03/01 Javascript
JavaScript数组基于交换的排序示例【冒泡排序】
2018/07/21 Javascript
服务端预渲染之Nuxt(使用篇)
2019/04/08 Javascript
微信小程序实现点击效果
2019/06/21 Javascript
教你搭建按需加载的Vue组件库(小结)
2019/07/29 Javascript
Node.js在图片模板上生成二维码图片并附带底部文字说明实现详解
2019/08/07 Javascript
python解析发往本机的数据包示例 (解析数据包)
2014/01/16 Python
使用Python爬取最好大学网大学排名
2018/02/24 Python
Python中pillow知识点学习
2018/04/30 Python
selenium+python自动化测试之鼠标和键盘事件
2019/01/23 Python
python批量解压zip文件的方法
2019/08/20 Python
基于python的列表list和集合set操作
2019/11/24 Python
Pandas实现dataframe和np.array的相互转换
2019/11/30 Python
linux 下python多线程递归复制文件夹及文件夹中的文件
2020/01/02 Python
python 使用递归回溯完美解决八皇后的问题
2020/02/26 Python
解决keras加入lambda层时shape的问题
2020/06/11 Python
大学毕业生通用自我评价
2014/01/05 职场文书
会计岗位职责范本
2014/03/07 职场文书
班级标语大全
2014/06/21 职场文书
销售目标责任书
2014/07/23 职场文书
2014年向国旗敬礼活动方案
2014/09/27 职场文书
质量整改报告范文
2014/11/08 职场文书
2016幼儿园教师年度考核评语
2015/12/01 职场文书
股东协议书范本2016
2016/03/21 职场文书