为什么数组的length
属性不能在for in
循环中迭代?我有以下代码:
var a = new Array();
for (i in a) {
if (i === 'length')
alert(i)
};
上述内容并未导致任何警报。但是,如果我改变长度'字符串到'克隆',引发警报。我不明白这一点,因为两者的长度都很长。和克隆'似乎是Array对象的成员,如下所示:
console.dir(a)
在搜索Google时,我只找到了使用hasOwnProperty方法的建议。这没有任何帮助,只会导致两种情况都没有发出警报。
答案 0 :(得分:5)
Javascript中的for (i in a)
结构列出了标记为enumerable
的Javascript对象的属性。它列出了对象的所有可枚举属性,无论它们是直接在对象上还是通过原型继承。 ' enumerable`是一个属性的特定特征。您可以拥有可枚举或不可枚举的对象属性。
.length
属性未标记为可枚举,因此未使用for (i in a)
结构显示。如果您使用Object.defineProperty()
自行创建属性,则可以控制可枚举属性(以及其他几个属性)。如果您只是直接添加属性而不使用Object.defineProperty()
指定其自定义属性,则默认情况下该属性将是可枚举的。
For a variety of reasons,您永远不应该尝试使用for (i in a)
结构迭代数组的元素。该结构明确地设计为列出Javascript对象的可枚举属性,该对象将包括所有Array元素,但也可能包括其他可枚举属性(正如您所见)。数组元素应枚举为:
for (var i = 0, len = array.length; i < len; i++) {
// array[i]
}
或
array.forEach(function(val, index, array) {
// code here
});
关于.clone
的观察,这不是Array对象的标准属性。我猜测它可能已被某个第三方库添加到Array原型中,并且显然标记为可枚举,这解释了它在for (i in a)
循环中显示的原因。
.hasOwnProperty()
通常用于过滤原型上的属性,因此您只迭代直接应用于对象的属性(不是从原型继承),这解释了为什么它会过滤掉{{1属性(如果它在原型上)。
在任何情况下,如果您的目标是迭代数组的元素(而不是添加到Array对象的任何自定义属性),那么您应该使用上述两种迭代方法之一,然后您赢得了# t必须担心原型或Array对象本身上的.clone
或其他可枚举属性。