for(i in array)和for(var i = 0; i <array.length; i ++)之间的差异

wri*_*wan 15 javascript jquery for-loop

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

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

我从我那里获取一个JSONarray C# Webmethod并通过它调用它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>');
}
Run Code Online (Sandbox Code Playgroud)

附加的表添加了两行,将每个字段设置为"未定义".看到这张图片

但是,如果我用循环替换循环

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>');
}
Run Code Online (Sandbox Code Playgroud)

未定义的行消失.. 查看图像

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

编辑:

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

编辑-2

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

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

我在Master页面中声明了原型.

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);
    }
};
Run Code Online (Sandbox Code Playgroud)

它是否增加了数组长度.??

T.J*_*der 7

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

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

更多在这个SO答案我的博客.


另外:确保你在i某个地方宣布(你似乎不在你的第一个例子中).如果你不这样做,你会成为隐形全球恐怖的牺牲品.


我在Master页面中声明了原型.

Array.prototype.inArray = function ...

这就是为什么在for-in没有安全措施的情况下不使用循环数组的原因.再次,请参阅上面的链接.你for-in通过数组索引属性循环将循环("0","1",等-是的,他们真的字符串),并您已添加到函数名Array.prototype(inArray和这样).


Pau*_*per 5

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

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

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

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

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

var a = [];
a[0] = 0;
a[2] = 2;
Run Code Online (Sandbox Code Playgroud)

第一种方法将省略1. 第二种方式将包括索引1(与a[1]is undefined)。

类似的情况可能发生如下:

var a = [0, 1];
a.length = 3;
Run Code Online (Sandbox Code Playgroud)

就个人而言,我怀疑(3)。

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

编辑:从您的调试输出来看,似乎 (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;
    }
});
Run Code Online (Sandbox Code Playgroud)

(3) 检查是否在原型上定义了密钥。

for(var i in JSONRaw) {
    if(JSONRaw.hasOwnProperty(i)) {
        //do something
    }
}
Run Code Online (Sandbox Code Playgroud)

尽管由于潜在的陷阱(和更快的性能),大多数人只是使用第二个循环。