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压缩工具下载集合
Mar 06 Javascript
jQuery入门知识简介
Mar 04 Javascript
js函数返回多个返回值的示例代码
Nov 05 Javascript
JavaScript异步加载浅析
Dec 28 Javascript
JavaScript实现信用卡校验方法
Apr 07 Javascript
BootStrap3学习笔记(一)之网格系统
May 20 Javascript
javascript将中国数字格式转换成欧式数字格式的简单实例
Aug 02 Javascript
Bootstrap风格的WPF样式
Dec 07 Javascript
微信小程序(六):列表上拉加载下拉刷新示例
Jan 13 Javascript
webpack3之loader全解析
Oct 26 Javascript
js blob类型url的视频下载问题的解决
Nov 29 Javascript
JavaScript直接调用函数与call调用的区别实例分析
May 22 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和ACCESS写聊天室(九)
2006/10/09 PHP
PHP 递归效率分析
2009/11/24 PHP
php 调试利器debug_print_backtrace()
2012/07/23 PHP
php使用cookie显示用户上次访问网站日期的方法
2015/01/26 PHP
php 使用array函数实现分页
2015/02/13 PHP
使用GD库生成带阴影文字的图片
2015/03/27 PHP
Laravel学习教程之View模块详解
2017/09/18 PHP
PHP常用函数之base64图片上传功能详解
2019/10/21 PHP
YII2框架中ActiveDataProvider与GridView的配合使用操作示例
2020/03/18 PHP
JavaScript 的方法重载效果
2009/08/07 Javascript
JS如何将UTC格式时间转本地格式
2013/09/04 Javascript
Javascript表格翻页效果的具体实现
2013/10/05 Javascript
JavaScript+html5 canvas制作色彩斑斓的正方形效果
2016/01/27 Javascript
jquery中用jsonp实现搜索框功能
2016/10/18 Javascript
webpack+vue2构建vue项目骨架的方法
2018/01/09 Javascript
手写简单的jQuery雪花飘落效果实例
2018/04/22 jQuery
element ui 表格动态列显示空白bug 修复方法
2018/09/04 Javascript
详解vue项目接入微信JSSDK的坑
2018/12/14 Javascript
Python中endswith()函数的基本使用
2015/04/07 Python
使用Python编写一个在Linux下实现截图分享的脚本的教程
2015/04/24 Python
Python中matplotlib中文乱码解决办法
2017/05/12 Python
Python正则捕获操作示例
2017/08/19 Python
python3基于OpenCV实现证件照背景替换
2018/07/18 Python
python hook监听事件详解
2018/10/25 Python
pyshp创建shp点文件的方法
2018/12/31 Python
Python获取基金网站网页内容、使用BeautifulSoup库分析html操作示例
2019/06/04 Python
PHP统计代码行数的小代码
2019/09/19 Python
python和php学习哪个更有发展
2020/06/17 Python
AVIS安飞士奥地利租车官网:提供奥地利、欧洲和全世界汽车租赁
2016/11/29 全球购物
土耳其时尚潮流在线购物网站:Trendyol
2017/10/10 全球购物
大学自我鉴定范文
2013/12/26 职场文书
2014年技术工作总结范文
2014/11/20 职场文书
Python 如何实现文件自动去重
2021/06/02 Python
试了下Golang实现try catch的方法
2021/07/01 Golang
CSS三大特性继承性、层叠性和优先级详解
2022/01/18 HTML / CSS
python双向链表实例详解
2022/05/25 Python