我被告知不要使用。。。在JavaScript中使用数组。为什么不呢?


当前回答

孤立地说,在数组中使用for没有错。For-in迭代对象的属性名,在“现成”数组的情况下,财产对应于数组索引。(像length、toString等内置属性不包含在迭代中。)

然而,如果您的代码(或您正在使用的框架)将自定义财产添加到数组或数组原型中,那么这些财产将包含在迭代中,这可能不是您想要的。

一些JS框架,如Prototype修改了Array原型。像JQuery这样的其他框架则不然,因此使用JQuery,您可以在中安全地使用。

如果你有疑问,你可能不应该使用。

迭代数组的另一种方法是使用for循环:

for (var ix=0;ix<arr.length;ix++) alert(ix);

然而,这有一个不同的问题。问题是JavaScript数组可能有“洞”。如果您将arr定义为:

var arr = ["hello"];
arr[100] = "goodbye";

然后数组有两个项目,但长度为101。在中使用for将产生两个索引,而for循环将产生101个索引,其中99的值为undefined。

其他回答

有三个原因你不应该使用。。在中迭代数组元素:

对于in将循环遍历数组对象的所有自己和继承的财产,这些属性不是DontEnum;这意味着,如果有人将财产添加到特定数组对象(这有合理的原因-我自己做过)或更改array.prototype(这在代码中被认为是错误的做法,应该与其他脚本一起工作),这些财产也会被迭代;通过检查hasOwnProperty()可以排除继承的财产,但这对数组对象本身中设置的财产没有帮助对于中不能保证保留元素顺序它的速度很慢,因为您必须遍历数组对象的所有财产及其整个原型链,并且仍然只能获取属性的名称,即要获取值,需要进行额外的查找

孤立地说,在数组中使用for没有错。For-in迭代对象的属性名,在“现成”数组的情况下,财产对应于数组索引。(像length、toString等内置属性不包含在迭代中。)

然而,如果您的代码(或您正在使用的框架)将自定义财产添加到数组或数组原型中,那么这些财产将包含在迭代中,这可能不是您想要的。

一些JS框架,如Prototype修改了Array原型。像JQuery这样的其他框架则不然,因此使用JQuery,您可以在中安全地使用。

如果你有疑问,你可能不应该使用。

迭代数组的另一种方法是使用for循环:

for (var ix=0;ix<arr.length;ix++) alert(ix);

然而,这有一个不同的问题。问题是JavaScript数组可能有“洞”。如果您将arr定义为:

var arr = ["hello"];
arr[100] = "goodbye";

然后数组有两个项目,但长度为101。在中使用for将产生两个索引,而for循环将产生101个索引,其中99的值为undefined。

一个重要的方面是。。。in-only迭代包含在对象中的财产,该对象的可枚举属性属性设置为true。因此,如果尝试使用for对对象进行迭代。。。然后,如果任意财产的可枚举属性为false,则可能会丢失这些属性。很有可能更改普通Array对象的可枚举属性属性,以便不枚举某些元素。虽然一般来说,属性属性倾向于应用于对象中的函数财产。

可以通过以下方式检查财产的可枚举属性属性的值:

myobject.propertyIsEnumerable('myproperty')

或获取所有四个属性属性:

Object.getOwnPropertyDescriptor(myobject,'myproperty')

这是ECMAScript 5中提供的一个特性——在早期版本中,无法更改可枚举属性属性的值(它总是设置为true)。

截至2016年(ES6),我们可能会使用for…for数组迭代,正如John Slegers已经注意到的那样。

我只想添加一个简单的演示代码,以使事情更清楚:

Array.prototype.foo = 1;
var arr = [];
arr[5] = "xyz";

console.log("for...of:");
var count = 0;
for (var item of arr) {
    console.log(count + ":", item);
    count++;
    }

console.log("for...in:");
count = 0;
for (var item in arr) {
    console.log(count + ":", item);
    count++;
    }

控制台显示:

for...of:

0: undefined
1: undefined
2: undefined
3: undefined
4: undefined
5: xyz

for...in:

0: 5
1: foo

换句话说:

对于的计数从0到5,并且还忽略Array.prototype.foo。它显示数组值。对于中只列出了5个,忽略了未定义的数组索引,但添加了foo。它显示数组属性名称。

因为如果你不小心的话,它会迭代属于原型链上对象的财产。

您可以使用。。在中,只需确保使用hasOwnProperty检查每个属性。