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


当前回答

以下是这种做法(通常)不好的原因:

对于in循环迭代它们自己的所有可枚举财产及其原型的可枚举财产。通常在数组迭代中,我们只需要迭代数组本身。即使您自己可能没有向数组中添加任何内容,但您的库或框架可能会添加一些内容。

例子:

Array.prototype.hithere=“此处”;var数组=[1,2,3];for(let el in array){//hithere属性也将被迭代控制台日志(el);}

对于in循环不能保证特定的迭代顺序。尽管现在大多数现代浏览器中通常都能看到isorder,但仍然没有100%的保证。对于in循环忽略未定义的数组元素,即尚未分配的数组元素。

例子::

常量arr=[];arr[3]=“foo”;//将阵列大小调整为4arr[4]=未定义;//添加另一个未定义值的元素//遍历数组,for循环确实显示了未定义的元素for(设i=0;i<arr.length;i++){控制台日志(arr[i]);}console.log('\n');//for in忽略未定义的元素for(let el in arr){控制台日志(arr[el]);}

其他回答

因为。。。in通过持有数组的对象枚举,而不是数组本身。如果我向数组原型链中添加了一个函数,那么它也将包含在内。即。

Array.prototype.myOwnFunction = function() { alert(this); }
a = new Array();
a[0] = 'foo';
a[1] = 'bar';
for(x in a){
 document.write(x + ' = ' + a[x]);
}

这将写入:

0 = foo
1 = bar
myOwnFunction = function() { alert(this); }

而且,由于您永远无法确定不会向原型链中添加任何内容,因此只需使用for循环来枚举数组:

for(i=0,x=a.length;i<x;i++){
 document.write(i + ' = ' + a[i]);
}

这将写入:

0 = foo
1 = bar

原因是一个构造:

变量a=[];//创建新的空数组。a[5]=5;//调整数组大小的完全合法的JavaScript。对于(var i=0;i<a.length;i++){//按照每个人的预期,在从0到5的数字索引上重复。控制台日志(a[i]);}/*将显示:未定义未定义未定义未定义未定义5.*/

有时可能完全不同:

变量a=[];a[5]=5;for(a中的var x){//仅显示显式设置的索引“5”,并忽略0-4console.log(x);}/*将显示:5.*/

还要考虑JavaScript库可能会这样做,这会影响您创建的任何数组:

//在JavaScript库的深处。。。Array.prototype.foo=1;//现在你不知道下面的代码会做什么。变量a=[1,2,3,4,5];for(a中的var x){//现在foo是每个数组的一部分//将在此处显示为“x”值。console.log(x);}/*将显示:01.2.3.4.食品*/

这不一定是坏的(根据您正在做的事情),但在数组的情况下,如果在Array.prototype中添加了一些东西,那么您将得到奇怪的结果。您希望此循环运行三次:

var arr = ['a','b','c'];
for (var key in arr) { ... }

如果一个名为helpfulUtilityMethod的函数被添加到Array的原型中,那么循环将运行四次:键将是0、1、2和helpfulUtilityMethod。如果你只需要整数,噢。

除了其他答案中给出的原因外,如果需要计算计数器变量,您可能不想使用“for…In”结构,因为循环会迭代对象财产的名称,因此该变量是一个字符串。

例如

for (var i=0; i<a.length; i++) {
    document.write(i + ', ' + typeof i + ', ' + i+1);
}

将写入

0, number, 1
1, number, 2
...

鉴于

for (var ii in a) {
    document.write(i + ', ' + typeof i + ', ' + i+1);
}

将写入

0, string, 01
1, string, 11
...

当然,这可以通过包括

ii = parseInt(ii);

但第一种结构更直接。

孤立地说,在数组中使用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。