为什么在数组迭代中使用“for ... in”是一个坏主意?

我被告知不要在JavaScript for...in使用数组。 为什么不?


原因是一个构造:

var a = []; // Create a new empty array.
a[5] = 5;   // Perfectly legal JavaScript that resizes the array.

for (var i = 0; i < a.length; i++) {
    // Iterate over numeric indexes from 0 to 5, as everyone expects.
    console.log(a[i]);
}

/* Will display:
   undefined
   undefined
   undefined
   undefined
   undefined
   5
*/

for-in语句本身并不是一个“坏习惯”,但它可能被错误地用于例如遍历数组或类似数组的对象。

for-in语句的目的是枚举对象属性。 这个语句将在原型链中继续,并且枚举继承的属性,这有时是不希望的。

此外,规范不保证迭代的顺序,这意味着如果要“迭代”数组对象,则使用此语句不能确定将按数字顺序访问属性(数组索引)。

例如,在JScript(IE <= 8)中,甚至在Array对象上枚举的顺序也是在创建属性时定义的:

var array = [];
array[2] = 'c';
array[1] = 'b';
array[0] = 'a';

for (var p in array) {
  //... p will be "2", "1" and "0" on IE
}

另外,就继承属性而言,例如,如果您扩展Array.prototype对象(就像MooTools那样使用某些库),那么该属性也将被枚举:

Array.prototype.last = function () { return this[this.length-1]; };

for (var p in []) { // an empty array
  // last will be enumerated
}

正如我之前所说的遍历数组或类似数组的对象,最好的办法是使用一个顺序循环,比如一个普通的for / while循环。

如果只想枚举对象的属性(不是继承的),可以使用hasOwnProperty方法:

for (var prop in obj) {
  if (obj.hasOwnProperty(prop)) {
    // prop is not inherited
  }
}

有些人甚至建议直接从Object.prototype调用该方法,以避免有人向我们的对象添加名为hasOwnProperty的属性时出现问题:

for (var prop in obj) {
  if (Object.prototype.hasOwnProperty.call(obj, prop)) {
    // prop is not inherited
  }
}

有三个原因让你不应该使用for..in遍历数组元素:

  • for..infor..in不是DontEnum的数组对象的所有自己的和继承的属性; 这意味着如果某人向特定的数组对象添加了属性(这里有合理的理由 - 我自己也这么做了),或者改变了Array.prototype (在代码中被认为是不好的做法,它应该与其他脚本一起工作),这些属性也会迭代; 继承的属性可以通过检查hasOwnProperty()来排除,但这不会帮助你使用数组对象本身的属性

  • for..in不能保证元素排序

  • 它很慢,因为您必须遍历数组对象及其整个原型链的所有属性,并且仍然只获取属性的名称,即获取该值,则需要额外的查找

  • 链接地址: http://www.djcxy.com/p/1883.html

    上一篇: Why is using "for...in" with array iteration a bad idea?

    下一篇: Is reading the `length` property of an array really that expensive an operation in JavaScript?