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


当前回答

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

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

myobject.propertyIsEnumerable('myproperty')

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

Object.getOwnPropertyDescriptor(myobject,'myproperty')

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

其他回答

您应该只在属性列表上使用for(var x in y),而不是在对象上(如上所述)。

对于在处理JavaScript中的对象时,in是有用的,但对Array来说不是,但我们仍然不能说这是错误的方法,但不建议这样做,请看下面的示例,使用for。。。循环中:

let txt = "";
const person = {fname:"Alireza", lname:"Dezfoolian", age:35}; 
for (const x in person) {
    txt += person[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 

好了,让我们现在使用Array:

let txt = "";
const person = ["Alireza", "Dezfoolian", 35]; 
for (const x in person) {
   txt += person[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 

正如你看到的结果一样。。。

但让我们尝试一下,让我们为Array原型。。。

Array.prototype.someoneelse = "someoneelse";

现在我们创建一个新的Array();

let txt = "";
const arr = new Array();
arr[0] = 'Alireza';
arr[1] = 'Dezfoolian';
arr[2] = 35;
for(x in arr) {
 txt += arr[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 someoneelse

你看到别人了!!!。。。在本例中,我们实际上循环通过新的Array对象!

这就是为什么我们需要使用。。小心,但情况并非总是这样。。。

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
  }
}

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

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

因为。。。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