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