for(i in array)和for(var i = 0; i

时间:2013-11-23 09:13:13

标签: javascript jquery for-loop

对于所有javascript / jquery家伙来说,这将是一个非常简单的问题。

我从过去2年开始编写javascript,今天我遇到了一个奇怪的问题。

我从C# Webmethod获取JSON阵列并通过jQuery.ajax()

调用它

当我这样做时

for (i in JSONRaw) {
    Index = Index + 1;
    $('#bottomGridDashboard').append('<tr> <td>' + Index + '</td> <td>' + JSONRaw[i].DisplayName + '</td> <td>' + JSONRaw[i].SpeedInKPH + '</td> <td><img src="' + JSONRaw[i].ImageURL + '" height="20px" alt="" /></td> <td>' + JSONRaw[i].DepotID + '</td> <td>' + JSONRaw[i].RouteID + '/' + JSONRaw[i].ScheduleID + '/' + JSONRaw[i].TripID + '</td> <td>' + JSONRaw[i].Direction + '</td> <td>' + JSONRaw[i].LastStop + '</td> <td> ' + JSONRaw[i].ETAMinutes + ' </td> </tr>');
}

附加表增加了两行,将每个字段设置为“未定义”。 See this Image

但是,如果我用

替换循环
for (var i = 0; i < JSONRaw.length;i++ ) {
    Index = Index + 1;
    $('#bottomGridDashboard').append('<tr> <td>' + Index + '</td> <td>' + JSONRaw[i].DisplayName + '</td> <td>' + JSONRaw[i].SpeedInKPH + '</td> <td><img src="' + JSONRaw[i].ImageURL + '" height="20px" alt="" /></td> <td>' + JSONRaw[i].DepotID + '</td> <td>' + JSONRaw[i].RouteID + '/' + JSONRaw[i].ScheduleID + '/' + JSONRaw[i].TripID + '</td> <td>' + JSONRaw[i].Direction + '</td> <td>' + JSONRaw[i].LastStop + '</td> <td> ' + JSONRaw[i].ETAMinutes + ' </td> </tr>');
}

未定义的行消失.. See the image

我为自己的愚蠢道歉,但我以前从未遇到任何此类问题。 可能是什么原因?

修改

阵列非常好。并且它没有漏洞。 另一个观察是未定义的属性仅出现在我的网格底部。我认为它正在处理两个额外的索引而不是数组长度。

修改-2

我的console.log向我展示了我的数组中的以下元素。

http://i.imgur.com/rI5TjdK.jpg

我已在主页面中声明原型。

Array.prototype.inArray = function (comparer) {
    for (var i = 0; i < this.length; i++) {
        if (comparer(this[i])) return true;
    }
    return false;
};


Array.prototype.pushIfNotExist = function (element, comparer) {
    if (!this.inArray(comparer)) {
        this.unshift(element);
    }
};

是否增加了数组长度。 ? ?

3 个答案:

答案 0 :(得分:7)

JavaScript的for-in和C#的foreach是完全不同的东西。除非使用适当的安全措施,否则不要使用for-in循环遍历数组,这不是它的用途。它遍历对象的可枚举属性,而不是数组索引或条目。

要么使用必要的安全措施,要么像第二个例子那样使用通用for,或者(如果可以依赖它)使用Array#forEach

this SO answeron my blog中的更多内容。


另外:确保你在某个地方声明i(你似乎不在你的第一个例子中)。如果你不这样做,你会成为The Horror of Implicit Globals的牺牲品。


  

我已在主页面中声明原型。

     

Array.prototype.inArray = function ...

这就是为什么在没有安全措施的情况下不使用for-in来循环数组的原因。再次,请参阅上面的链接。您的for-in循环将遍历数组索引属性("0""1",依此类推 - 是的,它们确实是字符串)而您添加到Array.prototypeinArray等)的功能名称。

答案 1 :(得分:4)

这两个循环有几种不同的方式。

(1)第一个应该是for (var i in JSONRaw)。在i上设置属性window可能会产生不明显的后果。

(2)JSONRaw不是数组,而是碰巧具有错误定义的length属性的对象。

(3)JSONRaw上设置的其他属性出现在第一个循环中。

(4)阵列可能有“洞”。例如,下面的数组在索引1处有一个洞。

var a = [];
a[0] = 0;
a[2] = 2;

第一种方法会省略1。第二种方式包括索引1a[1]undefined)。

类似情况可能发生如下:

var a = [0, 1];
a.length = 3;

我个人怀疑(3)。

在第一个循环中执行console.log可能会发现问题。

编辑:从您的调试输出中,似乎(3)是罪魁祸首。 inArraypushIfNotExist所有数组上的键,因此第一个for循环遍历它们。

如果您打算使用第一个循环,您有三个选择:

(1)不要在Array.prototype上添加这些功能。通常不鼓励添加内置原型。

(2)使用Object.defineProperty(在IE8中不起作用):

Object.defineProperty(Array.prototype, 'inArray', {
    enumerable: false,   //this makes it not show up in the for loop
    value: function (comparer) {
        for (var i = 0; i < this.length; i++) {
            if (comparer(this[i])) return true;
        }
        return false;
    }
});

(3)检查原型上是否定义了键。

for(var i in JSONRaw) {
    if(JSONRaw.hasOwnProperty(i)) {
        //do something
    }
}

虽然大多数人只是使用第二个循环,因为潜在的陷阱(和更快的性能)。

答案 2 :(得分:2)

简而言之,for ... in周期遍历keys object,而c-like for周期遍历数组索引。 JS没有那么强类型,因此它允许你获得两种方式,但是数组的正确方法只是第二种或'forEach'方法。您可以阅读更多on MDN