一,为什么不要用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。

for (var i=0;i<cars.length;i++)
{
document.write(cars[i] + "<br>");
}

详细出处参考:http://www.jb51.net/article/25036.htm

最新文章

  1. 在cygwin部署hadoop出现的问题:$ ./bin/hadoop version 显示错误: 找不到或无法加载主类 org.apache.hadoop.util.VersionInfo
  2. 守护进程demon.c
  3. 【BZOJ1951】【SDOI2010】古代猪文 Lucas定理、中国剩余定理、exgcd、费马小定理
  4. shell脚本学习--shell中的变量$
  5. vscode调试HTML
  6. RSS FEED的应用
  7. 第06篇 MyEclipse 2016 安装/破解
  8. jquery扩展 $.fn
  9. request对象多种方法封装表单数据
  10. Android单元测试初探——Instrumentation(转载)
  11. XMPPFrameWork IOS 开发(一)xmpp简介
  12. Nginx配置IP白名单和黑名单
  13. Linux下的定时任务 - Cron服务
  14. 第七节:Trigger(SimpleTrigger、CronTrigger)哑火(MisFire)策略 :
  15. stark组件开发之编辑功能实现
  16. 2019-4-25 html学习笔记
  17. CentOS Linux更改MySQL数据库目录位置具体操作
  18. hive的row_number()函数
  19. QT4编程过程中遇到的问题及解决办法
  20. UTF-8和GBK编码转换iconv

热门文章

  1. 备份xx
  2. React-Router ---withRouter
  3. javaee IO流作业02
  4. Dart 调用C语言混合编程
  5. spring boot jpa 无法使用findOne
  6. PHP和zookeeper结合实践
  7. canvas实现圆框图片
  8. Problem 52
  9. 【ABCD组】Scrum meeting 2
  10. QT5.4.1在ARM开发板上不能显示汉字