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 19 Javascript
页面调用单个swf文件,嵌套出多个方法。
Nov 21 Javascript
jQuery实现的多屏图像图层切换效果实例
May 07 Javascript
javascript实现倒计时并弹窗提示特效
Jun 05 Javascript
实例详解angularjs和ajax的结合使用
Oct 22 Javascript
JavaScript的设计模式经典之代理模式
Feb 24 Javascript
jquery动态添加文本并获取值的方法
Oct 12 Javascript
BootStrap Table 获取同行不同列元素的方法
Dec 19 Javascript
vue获取input输入值的问题解决办法
Oct 17 Javascript
Vue的编码技巧与规范使用详解
Aug 28 Javascript
Vue事件处理原理及过程详解
Mar 11 Javascript
vue响应式原理与双向数据的深入解析
Jun 04 Vue.js
来自国外的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
Laravel开启跨域请求的方法
2019/10/13 PHP
javawscript 三级菜单的实现原理
2009/07/01 Javascript
js 处理数组重复元素示例代码
2013/12/27 Javascript
JS按回车键实现登录的方法
2014/08/25 Javascript
浅谈Javascript的静态属性和原型属性
2015/05/07 Javascript
JS留言功能的简单实现案例(推荐)
2016/06/23 Javascript
用jQuery旋转插件jqueryrotate制作转盘抽奖
2017/02/10 Javascript
Vuex利用state保存新闻数据实例
2017/06/28 Javascript
JS判断数组那点事
2017/10/10 Javascript
详解Nuxt.js Vue服务端渲染摸索
2018/02/08 Javascript
微信小程序input框中加入小图标的实现方法
2018/06/19 Javascript
vue 根据数组中某一项的值进行排序的方法
2018/08/30 Javascript
微信小程序使用swiper组件实现层叠轮播图
2018/11/04 Javascript
jQuery实现颜色打字机的完整代码
2020/03/19 jQuery
Vue前端判断数据对象是否为空的实例
2020/09/02 Javascript
[00:20]TI9观赛名额抽取Ⅱ
2019/07/24 DOTA
在Python的Django框架中实现Hacker News的一些功能
2015/04/17 Python
Python实现获取本地及远程图片大小的方法示例
2018/07/21 Python
在linux下实现 python 监控usb设备信号
2019/07/03 Python
python将excel转换为csv的代码方法总结
2019/07/03 Python
python使用flask与js进行前后台交互的例子
2019/07/19 Python
Django CBV与FBV原理及实例详解
2019/08/12 Python
python实现宿舍管理系统
2019/11/22 Python
记录一下scrapy中settings的一些配置小结
2020/09/28 Python
利用CSS3实现自定义滚动条代码分享
2016/08/18 HTML / CSS
微软澳洲官方网站:Microsoft Australia
2017/01/10 全球购物
Nebula美国官网:便携式投影仪
2019/03/15 全球购物
SportsDirect.com新加坡:英国第一体育零售商
2019/03/30 全球购物
西班牙Polo衫品牌:Polo Club
2020/08/09 全球购物
基于Python 函数和方法的区别说明
2021/03/24 Python
总经理办公室主任岗位职责
2013/11/12 职场文书
体育活动总结范文
2014/05/04 职场文书
学校拾金不昧表扬信
2015/01/16 职场文书
艺术节开幕词
2015/01/28 职场文书
小学语文继续教育研修日志
2015/11/13 职场文书
python实现简单的井字棋
2021/05/26 Python