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中RadioButtonList的功能及用法实例介绍
Aug 23 Javascript
SyntaxHighlighter 3.0.83使用笔记
Jan 26 Javascript
AngularJS 简单应用实例
Jul 28 Javascript
JavaScript的数据类型转换原则(干货)
Mar 15 Javascript
浅谈Vue组件及组件的注册方法
Aug 24 Javascript
解决vue select当前value没有更新到vue对象属性的问题
Aug 30 Javascript
element-ui表格合并span-method的实现方法
May 21 Javascript
关于JSON解析的实现过程解析
Oct 08 Javascript
jQuery实现验证用户登录
Dec 10 jQuery
Vue+Element UI 树形控件整合下拉功能菜单(tree + dropdown +input)
Aug 28 Javascript
Vue.js中v-for指令的用法介绍
Mar 13 Vue.js
Moment的feature导致线上bug解决分析
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 中的面向对象编程:通向大型 PHP 工程的办法
2006/12/03 PHP
编写安全 PHP应用程序的七个习惯深入分析
2013/06/08 PHP
PHP小技巧之JS和CSS优化工具Minify的使用方法
2014/05/19 PHP
PHP7数组的底层实现示例
2019/08/25 PHP
window.navigate 与 window.location.href 的使用区别介绍
2013/09/21 Javascript
使用jQuery管理选择结果
2015/01/20 Javascript
jquery中animate的stop()方法作用实例分析
2015/01/30 Javascript
使用AOP改善javascript代码
2015/05/01 Javascript
BootStrap扔进Django里的方法详解
2016/05/13 Javascript
jQuery EasyUI之验证框validatebox实例详解
2017/04/10 jQuery
关于bootstrap日期转化,bootstrap-editable的简单使用,bootstrap-fileinput的使用详解
2017/05/12 Javascript
Angular 4依赖注入学习教程之ValueProvider的使用(七)
2017/06/04 Javascript
vue2.0 自定义日期时间过滤器
2017/06/07 Javascript
vue loadmore组件上拉加载更多功能示例代码
2017/07/19 Javascript
基于daterangepicker日历插件使用参数注意的问题
2017/08/10 Javascript
代码详解JS操作剪贴板
2018/02/11 Javascript
Nodejs下使用gm圆形裁剪并合成图片的示例
2018/02/22 NodeJs
常用的 JS 排序算法 整理版
2018/04/05 Javascript
js监听html页面的上下滚动事件方法
2018/09/11 Javascript
解决layer 关闭当前弹窗 关闭遮罩层 input值获取不到的问题
2019/09/25 Javascript
[04:03][TI9趣味短片] 小鸽子茶话会
2019/08/20 DOTA
python基础教程之实现石头剪刀布游戏示例
2014/02/11 Python
Python中MySQLdb和torndb模块对MySQL的断连问题处理
2015/11/09 Python
利用python实现在微信群刷屏的方法
2019/02/21 Python
将Python字符串生成PDF的实例代码详解
2019/05/17 Python
python使用writerows写csv文件产生多余空行的处理方法
2019/08/01 Python
在Python中画图(基于Jupyter notebook的魔法函数)
2019/10/28 Python
Python的Tqdm模块实现进度条配置
2021/02/24 Python
西班牙伏林航空公司:Vueling
2016/08/05 全球购物
欧洲最大的品牌水上运动服装和设备在线零售商:Wuituit Outlet
2018/05/05 全球购物
英国第一摩托车和摩托车越野配件商店:GhostBikes
2019/03/10 全球购物
好的自荐信的要求
2013/10/30 职场文书
优秀员工自荐书
2013/12/19 职场文书
化学教育专业求职信
2014/07/08 职场文书
2014年环卫工作总结
2014/11/22 职场文书
幼儿园小班个人总结
2015/02/12 职场文书