数组Array进行原型prototype扩展后带来的for in遍历问题

不同的程序语言都有多种循环语句,而且功能是差不多的,当然使用场合还是有些区别的,比如for与for in,for in比较好用,它不需要预先知道对象属性的长度。
通常在JavaScript中用for与for in遍历数组结果是没有什么区别的,它的循环变量i都是从0开始的数组索引(for in如果遍历的是非数组对象的属性集合,则这个i就是属性名,或称之为key)。另外要注意一点是:用for in遍历数组,循环变量i是字符串类型的。如果对Array进行原型扩展后,再用for in来对数组进行遍历时就要注意些问题了。
测试代码:
复制代码代码如下:

Array.prototype.max = function() 
{ 
return Math.max.apply({}, this); 
}; 
var company = ['Adobe','Apple','Google','Intel','Microsoft','Oracle','IBM','SUN']; 
alert(company.length); 

这里输出的长度是8,与上面定义的数组长度一致
下面循环了9次,在IE6、IE7第一次循环时i值不是0而是上面原型扩展的方法名max,而在IE8、FF浏览器最后一次循环时i值才为max

for (var i in company) 
{ 
alert('index is:'+i+'\nvalue is:'+company[i]); 
} 

此时,你若仅想打印上面8个公司列表,用for in循环是不行了,即使你非要这样做,也要在循环内部做点判断,比如像下面这样:

for (var i in company) 
{ 
if (!isNaN(i)) 
alert('index is:'+i+'\nvalue is:'+company[i]); 
}

当然,为了安全起见,也不要那么懒,就写成普通的for循环才是最科学的,像下面这样:

for (var i=0; i< company.length; i++) 
{ 
alert('index is:'+i+'\nvalue is:'+company[i]); 
} 

这种对数组原型扩展属性带来的循环问题通常是导致你得不到预期的结果,但不注意也可能给你代码带来难以发现的问题,看看下面的例子:

var userInfo = [
    ["Tom",21,"020-12345678"],
    ["Mike",23,"020-87654321"]
]; 

显然这里是数组嵌套

for (var i in userInfo) 
{ 
alert('Name:' + userInfo[i][0] + '\nAge:' + userInfo[i][1] + '\nPhone:' + userInfo[i][2]); 
} 

此时通过userInfo[i][0]可能根本得不到你预想的值,比如在这个循环中,你将看到有一次值为undefined的结果,这是因为当i值为max时,userInfo[i]是一个function而不是像这样的子数组 [“Tom”,21,”020-12345678”]

一般来说for in是用来遍历对象属性的,而数组还是要用for来遍历(当然数组也是对象)。据了解,for要比for in的遍历效率高,另外像C#、ActionScript3.0还有foreach循环,这将是效率最高的循环,不过JavaScript没有这种循环。最科学的数组遍历应该像这样:使用普通的for循环,而且预存数组长度。

var company = ['Adobe', 'Apple', 'Google', 'Intel', 'Microsoft', 'Oracle', 'IBM', 'SUN']; 
for (var i = 0, companyNum = company.length; i < companyNum; i++) 
{ 
alert('index is:' + i + '\nvalue is:' + company[i]); 
} 

你可能感兴趣的:(javascript)