0

这困扰了我一段时间,请参阅我的 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

4 回答 4

11

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

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

您应该改为检查 using 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)

于 2012-04-20T15:48:14.907 回答
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);
        }
    };
}
于 2012-04-20T15:49:43.503 回答
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 循环:for...in 与 for

于 2012-04-20T15:51:02.113 回答
1

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

于 2012-04-20T16:13:17.803 回答