【问题标题】:Difference between for(i in array) and for(var i=0;i<array.length;i++) [duplicate]for(i in array) 和 for(var i=0;i<array.length;i++) 之间的区别 [重复]
【发布时间】:2023-03-29 05:02:02
【问题描述】:

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

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

我正在从我的C# Webmethod 获取一个 JSONarray,并由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

我为我的愚蠢道歉,但我以前从未遇到过这样的问题。 可能是什么原因??

编辑:

数组非常好。而且里面没有洞。 另一个观察结果是未定义的属性只出现在我的网格底部。我认为它处理的索引比数组长度多两个。

EDIT-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);
    }
};

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

【问题讨论】:

  • 把你问题的全部内容放在你的问题中,不要链接到站外。您可以发布图片,尽管使用console.log 输出,最好将其包含为文本。
  • 我以后会处理的.. :)

标签: javascript jquery for-loop


【解决方案1】:

简而言之,for ... in 循环遍历 objectkeys,而类似 c 的 for 循环遍历数组索引。 JS 的类型不是那么强,因此它允许您同时使用两种方法,但数组的正确方法只是第二种方法或“forEach”方法。你可以阅读更多on MDN

【讨论】:

  • “但数组的正确方法只有第二个” 一点也不。 Array#forEach 是另一种正确的方式; for-in 有适当的使用数组(特别是稀疏数组),你只需要使用正确的保护措施。
  • 同意,forEach 是完全正确的,但我不使用它,因为有时我会支持 IE8,在这种情况下我需要编写 polyfill。如果您不需要支持这种古老的软件,您可以安全地使用它。它仍然需要 [].prototype 技巧来与实时集合一起使用,但你提到它很好。我会把它添加到我的答案中。
【解决方案2】:

这两个循环有几种不同之处。

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

(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
    }
}

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

【讨论】:

  • 谢谢保罗。但是我没有看到任何其他将“i”声明为全局对象或在我的 JSON 数组中看到任何漏洞。数组的 Console.log 向我显示了一个正确的数组,没有任何未定义的属性。
  • @writeToBhuwan,我可能不清楚...我的意思是console.log inside 第一个循环(所以你会有几个值)。
  • 查看我的问题中的编辑......我的循环中的控制台日志(array[i])
  • 感谢您的帮助。接受你的作为答案。虽然我并不完全满意。
  • @writeToBhuwan,查看更新后的答案。
【解决方案3】:

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 等)。

【讨论】:

  • 没有这样的全局变量。如果您愿意,我可以发布我的整个 javascript
  • 我已经使用 i(没有声明) 很长时间了,它一直运行良好。 (不想冒犯,只是期待一些清晰)
  • @writeToBhuwan:除非您在某处声明i,否则您隐式使用它会创建一个全局变量。有关详细信息,请参阅链接。这意味着如果您在两个函数中执行此操作,并且一个调用另一个,它们将相互干扰。
  • 我是否应该将“i”声明为全局变量并将值设置为 0?
  • @writeToBhuwan:不。您应该在使用它的函数中声明它。
猜你喜欢
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 2019-11-07
  • 1970-01-01
相关资源
最近更新 更多