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


当前回答

主要有两个原因:

One

就像其他人所说的那样,您可能会得到不在数组中或从原型继承的密钥。因此,假设库向Array或Object原型添加了一个属性:

Array.prototype.someProperty = true

您可以将其作为每个阵列的一部分:

for(var item in [1,2,3]){
  console.log(item) // will log 1,2,3 but also "someProperty"
}

可以使用hasOwnProperty方法解决此问题:

var ary = [1,2,3];
for(var item in ary){
   if(ary.hasOwnProperty(item)){
      console.log(item) // will log only 1,2,3
   }
}

但这对于使用for in循环迭代任何对象都是正确的。

Two

通常,数组中项目的顺序很重要,但for in循环不一定以正确的顺序迭代,这是因为它将数组视为对象,这是在JS中实现的方式,而不是数组。这看起来是一件小事,但它确实会破坏应用程序,而且很难调试。

其他回答

因为它通过对象字段而不是索引枚举。你可以用索引“length”获得值,我怀疑你是否想要这个。

TL&DR:在数组中使用for in循环并不是坏事,事实上恰恰相反。

我认为如果在数组中正确使用,for in循环是JS的瑰宝。你应该完全控制你的软件,并知道你在做什么。让我们看看上面提到的缺点,并逐一反驳它们。

它还遍历继承的财产:首先,对Array.prototype的任何扩展都应该使用Object.defineProperty()完成,并且它们的可枚举描述符应该设置为false。任何没有这样做的库都不应该被使用。添加到继承链中的财产稍后会被计数:当按Object.setPrototypeOf或按类扩展进行数组子分类时。您应该再次使用Object.defineProperty(),它默认将可写、可枚举和可配置的属性描述符设置为false。让我们在这里看到一个数组子类示例。。。

函数堆栈(…a){var stack=新数组(…a);Object.setPrototypeOf(堆栈,stack.prototype);返回堆栈;}Stack.prototype=对象.create(Array.prototype);//现在堆栈可以完全访问数组方法。Object.defineProperty(Stack.prototype,“constructor”,{value:Stack});//现在Stack是一个合适的构造函数Object.defineProperty(Stack.prototype,“peak”,{value:function(){//将Stack“only”方法添加到Stack.prototype。返回this[this.length-1];}});var s=新堆栈(1,2,3,4,1);console.log(s.peak());s[s.length]=7;console.log(“长度:”,s.length);s.push(42);console.log(JSON.stringify);console.log(“长度:”,s.length);for(var i in s)console.log(s[i]);

所以你看。。因为您关心代码,所以in循环现在是安全的。

for in循环很慢:见鬼,没有。如果你在不时需要的稀疏数组上循环,这是迄今为止最快的迭代方法。这是人们应该知道的最重要的表演技巧之一。让我们看一个例子。我们将在稀疏数组上循环。

变量a=[];a[0]=“零”;a[10000000]=“1000万”;console.time(“用于数组a上的循环:”);对于(var i=0;i<a.length;i++)a[i]&&console.log(a[i]);console.timeEnd(“用于数组a上的循环:”);console.time(“用于数组a上的循环:”);对于(a中的var i)a[i]&&console.log(a[i]);console.timeEnd(“用于数组a上的循环中:”);

for in循环在遍历数组时将索引转换为字符串。例如,在下面的代码中,在用i+1初始化j的第二个循环中,i是索引,但在字符串(“0”、“1”等)中,js中的number+string是字符串。如果js遇到“0”+1,则返回“01”。

var maxProfit=函数(价格){设maxProfit=0;for(让我输入价格){for(设j=i+1;j<prices.length;j++){console.log(价格[j]-价格[i],“i,j”,i,j,类型i,类型j);如果((prices[j]-prices[i])>maxProfit)maxProfit=(prices[j]-prices[i]);}}return maxProfit;};最大利润([7,1,5,3,6,4]);

除了其他问题之外,“for…In”语法可能更慢,因为索引是字符串,而不是整数。

var a = ["a"]
for (var i in a)
    alert(typeof i)  // 'string'
for (var i = 0; i < a.length; i++)
    alert(typeof i)  // 'number'

除了其他答案中给出的原因外,如果需要计算计数器变量,您可能不想使用“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);

但第一种结构更直接。