为什么JS在每个函数中都给出了太多?

时间:2012-04-20 15:44:58

标签: javascript object for-loop for-in-loop

这让我困扰了一段时间,请看我的jsfiddle:http://jsfiddle.net/DHR8Q/,其中包含以下javascript代码:

var id = "11111;22222;33333";

id = id.split(";");

alert(typeof id);

for (var i in id){
    alert(id[i]);
}​

当我将变量id拆分为字符“;”时,我使用for循环,我会假设i == 0,1,2因为字符串id被分成3部分,但事实并非如此。实际上i == 0,1,2,3,4...。为什么JavaScript会这样做?

4 个答案:

答案 0 :(得分:11)

因为您链接的jsFiddle包含Mootools库;它将自己的方法添加到Array.prototype

使用for in枚举数组时,它会遍历所有属性;包括那些方法;这就是你所看到的。

您应该使用hasOwnProperty()进行检查,或者 使用for(;;);

for (var i in id){
    if (id.hasOwnProperty(i)) {
        alert(id[i]);
    }
}​

(jsFiddle)

for (var i=0;i<id.length;i++) {
    alert(id[i]);
}

(jsFiddle)

答案 1 :(得分:4)

这是因为for... in遍历对象的所有属性(包括来自prototype的属性)。

当您在数组上for... in时,您将获得数组元素以及length属性以及Array.prototype的所有属性。

您可以使用hasOwnProperty

解决此问题
for (var i in id){
    if(id.hasOwnProperty(i){
        alert(id[i]);
    }
}​

尽管如此,我建议不要将for... in用于数组,请使用forEach

id.forEach(function(v){
    alert(v);
});

或者是一个好的'for循环:

for(var i=0, len=id.length; i<len; i++){
    alert(id[i]);
}

修改

forEach功能在后备浏览器中无法作为内置功能使用,因此您可以这样做:

if (typeof Array.prototype.forEach !== 'function') {
    Array.prototype.forEach = function(fn, thisObj) {
        var scope = thisObj || window,  L = this.length, i;
        for (i=0; i < L; ++i) {
            fn.call(scope, this[i], i, this);
        }
    };
}

答案 2 :(得分:2)

JS中的数组是对象。当你在一个数组上执行for ... in时,你会获得所有索引以及该对象的所有原型成员。在您的情况下,原型成员包括一堆数组函数。

您应该使用常规for循环来迭代数字索引。

来自emacs中JSShell的输出说明:

js> 
Multi-line input. Use two consecutive blank lines to eval.

var id = "11111;22222;33333"; 

id = id.split(";"); 

js> function say (x) {WScript.echo(x);}
js> for (var i in id) { say (i); } 
0
1
2
forEach
every
map
filter
remove
removeAt
indexOf
contains
js> for(var i=0;i<id.length;i++) { say (i + ": " + id[i]); } 
0: 11111
1: 22222
2: 33333
js>

另见:JavaScript Loops: for...in vs for

答案 3 :(得分:1)

你不应该将它用于数组,因为首先不保证顺序,其次这些用于列出对象的所有可枚举属性,这可能不适合Arrays,因为几个框架将属性添加到Array原型中得到枚举。