for(数组中的i)和for(var i=0;i<array.length;i++)之间的差异
Difference between for(i in array) and for(var i=0;i<array.length;i++)
这对javascript/jquery的所有人来说都是一个非常简单的问题。
在过去的两年里,我一直在编写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>');
}
附加的表增加了两行,将每个字段都设置为"未定义"。查看此图像
但是,如果我用替换循环
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>');
}
未定义的行将消失。。查看图像
我为我的愚蠢道歉,但我以前从未遇到过这样的问题。原因可能是什么??
编辑:
阵列非常好。而且上面没有洞。另一个观察结果是,未定义的属性只出现在我的网格底部。我认为它处理的两个额外索引超过了数组长度。
编辑-2
我的console.log向我展示了数组中的以下元素。
https://i.stack.imgur.com/jw8Sy.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);
}
};
它是在增加数组长度吗?
JavaScript的for-in
和C#的foreach
是完全不同的东西。除非使用适当的保护措施,否则不要使用for-in
循环遍历数组,这不是它的用途。它循环通过对象的可枚举属性,而不是数组索引或条目。
要么使用必要的保护措施,要么像第二个示例一样使用通用for
,或者(如果可以信赖的话)使用Array#forEach
。
在这个SO回答和我的博客上有更多内容。
另外:确保您在某个地方声明了i
(您似乎不在第一个示例中)。如果你不这样做,你就会成为隐式全球化的恐怖的牺牲品。
我已经在我的母版页中声明了原型。
Array.prototype.inArray = function ...
这就是为什么不使用for-in
在没有安全保护的情况下循环通过数组的原因。同样,请参阅上面的链接。您的for-in
循环将循环遍历数组索引属性("0"
、"1"
等等——是的,它们实际上是字符串)和以及添加到Array.prototype
的函数的名称(inArray
等等)。
这两个循环有几种不同之处。
(1) 第一个应该是for (var i in JSONRaw)
。在window
上设置属性i
可能会产生不明显的后果。
(2) JSONRaw
不是一个数组,而是一个恰好具有定义不清的length
属性的对象。
(3) 在第一个循环中出现了JSONRaw
上设置的其他属性。
(4) 阵列可能有"洞"。例如,下面的数组在索引1
处有一个洞。
var a = [];
a[0] = 0;
a[2] = 2;
第一种方法将省略CCD_ 23。第二种方式将包括索引1
(其中a[1]
是undefined
)。
类似的情况可能发生如下:
var a = [0, 1];
a.length = 3;
就我个人而言,我怀疑(3)。
在第一个循环中执行console.log
可能会揭示问题。
EDIT:从调试输出来看,(3)似乎是罪魁祸首。inArray
和pushIfNotExist
是所有数组上的键,因此第一个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
}
}
尽管大多数人只是使用第二个循环,因为存在潜在的陷阱(以及更快的性能)。
简而言之,for ... in
循环通过object
的keys
进行迭代,而类似c的for
循环通过数组索引进行迭代。JS不是强类型的,所以它允许您同时使用这两种方法,但数组的正确方法只有second或"forEach"方法。您可以在MDN上阅读更多信息。
- 为什么JavaScript在for循环为3时向所有4发出警报
- 另一个ajax调用中的Jquery ajax调用在for循环中没有按预期工作
- Is onfling available for html, html5
- Setting default onclick behavior for <img> tag in gene
- TypeError:在不兼容的接收器nodejs上调用了方法Uint8Array.length
- Array.length似乎不起作用;console.log则显示其他情况
- 我的javascript for循环不起作用
- For循环冻结Javascript
- 如何在for循环中添加事件侦听器
- Javascript setTimeout for an array
- 双“for”循环(循环)
- 在for循环中使用x.length时出现问题
- for(数组中的i)和for(var i=0;i<array.length;i++)之间的差异
- for (var x in array) 和 for (var x=0, y= array.length; x
- 无法读取 javascript for loop 中 null 的属性“length”
- Javascript:for(var i<array.length)v.s.for(数组中的e)
- 在for循环的每一次迭代中都会计算.length属性
- For循环遍历数组.Length只执行一次
- 无法读取property 'length'在For循环(jQuery)中未定义
- 在javascript中的for循环定义中使用arr[i]和arr.length的区别