我被告知不要使用。。。在JavaScript中使用数组。为什么不呢?
当前回答
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使用两种类型的变量:哈希表(关联数组)和数组(非关联)。
JavaScript将自动确定其通过项目的方式。因此,如果您知道数组确实是非关联的,可以使用(var i=0;i<=arrayLen;i++),并跳过自动检测迭代。
但在我看来,最好使用for/in,自动检测所需的过程非常小。
对此的真正答案将取决于浏览器解析器/解释JavaScript代码的方式。它可以在浏览器之间更改。
我想不出不使用for/in的其他目的;
//Non-associative
var arr = ['a', 'b', 'c'];
for (var i in arr)
alert(arr[i]);
//Associative
var arr = {
item1 : 'a',
item2 : 'b',
item3 : 'c'
};
for (var i in arr)
alert(arr[i]);
一个重要的方面是。。。in-only迭代包含在对象中的财产,该对象的可枚举属性属性设置为true。因此,如果尝试使用for对对象进行迭代。。。然后,如果任意财产的可枚举属性为false,则可能会丢失这些属性。很有可能更改普通Array对象的可枚举属性属性,以便不枚举某些元素。虽然一般来说,属性属性倾向于应用于对象中的函数财产。
可以通过以下方式检查财产的可枚举属性属性的值:
myobject.propertyIsEnumerable('myproperty')
或获取所有四个属性属性:
Object.getOwnPropertyDescriptor(myobject,'myproperty')
这是ECMAScript 5中提供的一个特性——在早期版本中,无法更改可枚举属性属性的值(它总是设置为true)。
因为如果你不小心的话,它会迭代属于原型链上对象的财产。
您可以使用。。在中,只需确保使用hasOwnProperty检查每个属性。
因为它通过对象字段而不是索引枚举。你可以用索引“length”获得值,我怀疑你是否想要这个。
截至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。它显示数组属性名称。