这让我困扰了一段时间,请看我的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会这样做?
答案 0 :(得分:11)
因为您链接的jsFiddle包含Mootools库;它将自己的方法添加到Array.prototype
。
使用for in
枚举数组时,它会遍历所有属性;包括那些方法;这就是你所看到的。
您应该使用hasOwnProperty()
进行检查,或者 使用for(;;);
for (var i in id){
if (id.hasOwnProperty(i)) {
alert(id[i]);
}
}
或
for (var i=0;i<id.length;i++) {
alert(id[i]);
}
答案 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>
答案 3 :(得分:1)
你不应该将它用于数组,因为首先不保证顺序,其次这些用于列出对象的所有可枚举属性,这可能不适合Arrays,因为几个框架将属性添加到Array原型中得到枚举。