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 相关文章推荐
11款基于Javascript的文件管理器
Oct 25 Javascript
javaScript call 函数的用法说明
Apr 09 Javascript
JavaScript中使用replace结合正则实现replaceAll的效果
Jun 04 Javascript
整理一些JavaScript的IE和火狐的兼容性注意事项
Mar 17 Javascript
自动刷新网页,自动刷新当前页面,JS调用
Jun 24 Javascript
浅谈Javascript数组的使用
Jul 29 Javascript
Vue.js每天必学之表单控件绑定
Sep 05 Javascript
react 应用多入口配置及实践总结
Oct 17 Javascript
从组件封装看Vue的作用域插槽的实现
Feb 12 Javascript
JS字符串常用操作方法实例小结
Jun 24 Javascript
vue中 数字相加为字串转化为数值的例子
Nov 07 Javascript
Vue 实现拨打电话操作
Nov 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生成短网址示例
2014/05/05 PHP
整理php防注入和XSS攻击通用过滤
2015/09/13 PHP
深入理解PHP 数组之count 函数
2016/06/13 PHP
PHP使用Redis长连接的方法详解
2018/02/12 PHP
实例讲解php实现多线程
2019/01/27 PHP
jQuery 技巧大全(新手入门篇)
2009/05/12 Javascript
js 对联广告、漂浮广告封装类(IE,FF,Opera,Safari,Chrome
2009/11/26 Javascript
jQuery实现的立体文字渐变效果
2010/05/17 Javascript
国外大牛IE版本检测!现在IE都到9了,IE检测代码
2012/01/04 Javascript
js实现鼠标悬停图片上时滚动文字说明的方法
2015/02/17 Javascript
JS判断当前页面是否在微信浏览器打开的方法
2015/12/08 Javascript
基于Bootstrap实现的下拉菜单手机端不能选择菜单项的原因附解决办法
2016/07/22 Javascript
JavaScript如何一次性展示几万条数据
2017/03/30 Javascript
bootstrap select插件封装成Vue2.0组件
2017/04/17 Javascript
Angular 4依赖注入学习教程之ValueProvider的使用(七)
2017/06/04 Javascript
微信小程序中post方法与get方法的封装
2017/09/26 Javascript
浅谈Angular 中何时取消订阅
2017/11/22 Javascript
nodejs基于WS模块实现WebSocket聊天功能的方法
2018/01/12 NodeJs
node中实现删除目录的几种方法
2019/06/24 Javascript
VUE前后端学习tab写法实例
2019/08/06 Javascript
[01:09:24]Ti4开幕式
2014/07/19 DOTA
python解析json实例方法
2013/11/19 Python
Python基于Tkinter实现的记事本实例
2015/06/17 Python
详解使用pymysql在python中对mysql的增删改查操作(综合)
2017/01/18 Python
python list排序的两种方法及实例讲解
2017/03/20 Python
python获取命令行输入参数列表的实例代码
2018/06/23 Python
Python装饰器语法糖
2019/01/02 Python
python3.8.3安装教程及环境配置的详细教程(64-bit)
2020/11/28 Python
MADE法国:提供原创设计师家具
2018/09/18 全球购物
工程项目经理岗位职责
2013/12/15 职场文书
计算机大学生职业生涯规划书范文
2014/02/19 职场文书
毕业论文致谢词
2015/05/14 职场文书
我在伊朗长大观后感
2015/06/16 职场文书
小数乘法教学反思
2016/02/22 职场文书
2021-4-5课程——SQL Server查询【3】
2021/04/05 SQL Server
使用refresh_token实现无感刷新页面
2022/04/26 Javascript