Javascript技巧之不要用for in语句对数组进行遍历

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

(0)

相关推荐

  • js中的for如何实现foreach中的遍历

    js中没有foreach这个关键字,但是可以用var v in array来实现遍历.但是需要注意的是, 拿到的是key而不是value.看例子: 复制代码 代码如下: <script type="text/javascript"> // 普通数组 var intArray = new Array(); intArray[0] = "第一个"; intArray[1] = "第二个"; for(var i = 0; i<intA

  • Javascript中八种遍历方法的执行速度深度对比

    前言 遍历数组或对象是一名程序员的基本素养之一. 然而遍历却不是一件简单的事, 优秀的程序员知道怎么去选择合适的遍历方法, 优化遍历效率. 本篇将带你走进JavaScript遍历的世界, 享受分析JS循环的快感. 本篇所有代码都可以直接运行, 希望您通读本篇后, 不止是浏览, 最好是亲手去实践下. 概述 js有如下两种数据需要经常遍历 数组(Array) 对象(Object) 同时又提供了如下8种方法方便我们遍历元素 for while(或do~while) forEach for in $.e

  • JQuery $.each遍历JavaScript数组对象实例

    查看一个简单的jQuery的例子来遍历一个JavaScript数组对象. var json = [ {"id":"1","tagName":"apple"}, {"id":"2","tagName":"orange"}, {"id":"3","tagName":"banana&q

  • JS数组的遍历方式for循环与for...in

    JS数组的遍历方法有两种: 第一种:一般的for循环,例如: var a = new Array("first", "second", "third") for(var i = 0;i < a.length; i++) { document.write(a[i]+","); } 输出的结果:fitst,second,third 第一种:用for...in 这种遍历的方式,例如: var arr = new Array(&

  • js数组循环遍历数组内所有元素的方法

    例,for(){}遍历数组 复制代码 代码如下: <script type="text/javascript"> <!--var arr = new Array(13.5,3,4,5,6);for(var i=0;i<arr.length;i++){ arr[i] = arr[i]/2.0;}alert(arr); //--> </script> 例,for in循环遍历数组 复制代码 代码如下: <html><body>

  • js Map List 遍历使用示例

    Map (exMap:{"name":"abc","sex",'male'}): 在不知道key的情况下遍历map: 网上说过这种方法: 复制代码 代码如下: for(var key in exMap){ Console.write("key:"+key+";value:"+exMap[key]);//经我考证,the key is undefined.So the method is not right.

  • JQuery遍历json数组的3种方法

    一.使用each遍历 复制代码 代码如下: $(function () { var tbody = "";            //------------遍历对象 .each的使用-------------            //对象语法JSON数据格式(当服务器端回调回来的对象数据格式是json数据格式,必须保证JSON的格式要求,回调的对象必须使用eval函数进行转化(否则将得不到Object).本文不作详细介绍服务器端回调的数据问题,我们将直接自定义对象)        

  • jquery遍历筛选数组的几种方法和遍历解析json对象

    jquery grep()筛选遍历数组 复制代码 代码如下: $().ready( function(){ var array = [1,2,3,4,5,6,7,8,9]; var filterarray = $.grep(array,function(value){ return value > 5;//筛选出大于5的 }); for(var i=0;i<filterarray.length;i++){ alert(filterarray[i]); } for (key in filtera

  • Javascript技巧之不要用for in语句对数组进行遍历

    一,为什么不要用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遍历,根据上下文确认t

  • 12个非常有用的JavaScript技巧

    在这篇文章中,我将分享12个非常有用的JavaScript技巧.这些技巧可以帮助你减少并优化代码. 1) 使用!!将变量转换成布尔类型 有时,我们需要检查一些变量是否存在,或者它是否具有有效值,从而将它们的值视为true.对于做这样的检查,你可以使用||(双重否定运算符),它能自动将任何类型的数据转换为布尔值,只有这些变量才会返回false:0,null,"",undefined或NaN,其他的都返回true.我们来看看这个简单的例子: function Account(cash) {

  • 21个值得收藏的Javascript技巧

    1  Javascript数组转换为CSV格式 首先考虑如下的应用场景,有一个Javscript的字符型(或者数值型)数组,现在需要转换为以逗号分割的CSV格式文件.则我们可以使用如下的小技巧,代码如下: 复制代码 代码如下: var fruits = ['apple', 'peaches', 'oranges', 'mangoes'];var str = fruits.valueOf(); 输出:apple,peaches,oranges,mangoes 其中,valueOf()方法会将Jav

  • 7个好用的JavaScript技巧分享(译)

    前言 就像所有其他编程语言一样,JavaScript也有许多技巧可以完成简单和困难的任务. 一些技巧广为人知,而其他技巧则足以让你大吃一惊. 让我们来看看你今天就可以开始使用的七个JavaScript技巧吧! 原文链接:davidwalsh.name/javascript-- 数组去重 数组去重可能比您想象的更容易: var j = [...new Set([1, 2, 3, 4, 4])] >> [1, 2, 3, 4] 很简单有木有! 过滤掉falsy值 是否需要从数组中过滤出falsy值

  • 4个值得收藏的Javascript技巧

    目录 前言 1.变量转字符串 2.普通对象 3.once 4.浏览器嗅探 在Chrome中执行 在Node中执行 在Chrome中执行 前言 学习一门语言的一种非常有效的方法就是阅读该编程语言开发的优秀开源项目的源代码. Vuejs是最好的Javascript开源项目之一. 1.变量转字符串 vue/src/shared/util.js 将值转换为字符串是一个非常常见的需求,在Javascript中,有两个函数将值转换为字符串: String() JSON.stringify() 这两个功能具有

  • AngularJS ng-repeat指令中使用track by子语句解决重复数据遍历错误问题

    本文实例讲述了AngularJS ng-repeat指令中使用track by子语句解决重复数据遍历错误问题.分享给大家供大家参考,具体如下: 我们可以使用ng-repeat指令遍历一个JavaScript数组,当数组中有重复元素的时候,AngularJS会报错: Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. R

  • Javascript数组循环遍历之forEach详解

    1.js 数组循环遍历. 数组循环变量,最先想到的就是 for(var i=0;i<count;i++)这样的方式了. 除此之外,也可以使用较简便的forEach 方式 2.forEach函数. Firefox 和Chrome 的Array 类型都有forEach的函数.使用如下: <!--Add by oscar999--> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> &l

  • C#中foreach语句使用break暂停遍历的方法

    本文实例讲述了C#中foreach语句使用break暂停遍历的方法.分享给大家供大家参考.具体分析如下: 下面的代码演示了在C#中使用foreach时如何通过break语句暂停数据遍历 using System; public class w3demo { public static void Main() { int sum = 0; int[] nums = new int[10]; // give nums some values for(int i = 0; i < 10; i++) n

  • java不用循环语句打印数组元素的实例

    实例如下: import java.util.Arrays; public class Test { public static void main(String[] args) { int[] array = {0,1,4,7,2,5,8,3,6,9}; System.out.println(Arrays.toString(array)); } } 以上这篇java不用循环语句打印数组元素的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • C#使用foreach语句搜索数组元素的方法

    本文实例讲述了C#使用foreach语句搜索数组元素的方法.分享给大家供大家参考.具体分析如下: 下面的代码通过foreach语句对数组遍历,然后对元素进行逐个比较的方法来查找数组中的元素 using System; public class Search { public static void Main() { int[] nums = new int[10]; int val; bool found = false; // give nums some values for(int i =

随机推荐