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 相关文章推荐
JavaScript将相对地址转换为绝对地址示例代码
Jul 19 Javascript
今天是星期几的4种JS代码写法
Sep 17 Javascript
JavaScript实现N皇后问题算法谜题解答
Dec 29 Javascript
JavaScript中的Math.LN2属性用法详解
Jun 12 Javascript
jQuery实现区域打印功能代码详解
Jun 17 Javascript
Bootstrap实现基于carousel.js框架的轮播图效果
May 02 Javascript
Vue拖拽组件开发实例详解
May 11 Javascript
详解Vue demo实现商品列表的展示
May 07 Javascript
Vue中图片Src使用变量的方法
Oct 30 Javascript
JS判断数组是否包含某元素实现方法汇总
Jun 24 Javascript
原生js实现无缝轮播图效果
Jan 28 Javascript
如何在CocosCreator里画个炫酷的雷达图
Apr 16 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 身份证号验证函数
2009/05/07 PHP
PHP之COOKIE支持详解
2010/09/20 PHP
php使用array_rand()函数从数组中随机选择一个或多个元素
2014/04/28 PHP
php正则preg_replace_callback函数用法实例
2015/06/01 PHP
php实现CSV文件导入和导出
2015/10/24 PHP
Extjs gridpanel 出现横向滚动条问题的解决方法
2011/07/04 Javascript
js实现数组去重、判断数组以及对象中的内容是否相同
2013/11/29 Javascript
javascript调试过程中找不到哪里出错的可能原因
2013/12/16 Javascript
jquery.post用法之type设置问题
2014/02/24 Javascript
让table变成exls的示例代码
2014/03/24 Javascript
基于jquery实现放大镜效果
2015/08/17 Javascript
全面解析JavaScript里的循环方法之forEach,for-in,for-of
2020/04/20 Javascript
jQuery 如何实现一个滑动按钮开关
2016/12/01 Javascript
html5+canvas实现支持触屏的签名插件教程
2017/05/08 Javascript
jQuery简单实现的HTML页面文本框模糊匹配查询功能完整示例
2018/05/09 jQuery
微信小程序自定义modal弹窗组件的方法详解
2020/12/20 Javascript
Python Property属性的2种用法
2015/06/21 Python
python实现class对象转换成json/字典的方法
2016/03/11 Python
python实现画圆功能
2018/01/25 Python
python3实现多线程聊天室
2018/12/12 Python
Python 词典(Dict) 加载与保存示例
2019/12/06 Python
使用pyinstaller逆向.pyc文件
2019/12/20 Python
使用Python操作ArangoDB的方法步骤
2020/02/02 Python
Html5导航栏吸顶方案原理与对比实现
2020/06/10 HTML / CSS
美国学校用品、教室和教学商店:Discount School Supply
2018/04/04 全球购物
德国大型和小型家用电器网上商店:Energeto
2019/05/15 全球购物
乌克兰巴士票购买网站:inBus
2021/03/12 全球购物
介绍一下linux的文件系统
2015/10/06 面试题
Java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?
2012/05/30 面试题
企业节能减排实施方案
2014/03/19 职场文书
高三霸气励志标语
2014/06/24 职场文书
2015年上半年物业工作总结
2015/03/30 职场文书
第一节英语课开场白
2015/06/01 职场文书
甲午风云观后感
2015/06/02 职场文书
Python的flask接收前台的ajax的post数据和get数据的方法
2021/04/12 Python
苹果电脑mac os中货币符号快捷输入
2022/02/17 杂记