通过“索引计数”,我假设您的意思是length
财产。在这种情况下,您的第一个问题的答案是“否”。该length
属性与数组的最高数字索引相关联。因此,例如,如果您有以下代码,arr.length
则将是4
:
var arr = [];
arr[3] = true;
arr.length; //is 4
但是,您提到了 for-in 循环,它在这种情况下具有奇怪的行为。如果我们(从上面)执行 for-in arr
,我们会得到以下结果:
var output = "";
for (i in arr) { //Don't do this!
output += i;
}
output; //is "3" (not "0123" as you might expect)
正如我所提到的,原型属性对长度没有影响:
Array.prototype.foo = true;
var arr = [];
arr[3] = true;
arr.length; //is 4
但是,它们确实会影响 for-in 循环(在正常情况下):
var output = "";
for (i in arr) { //arr from the previous code block.
output += i;
}
output; //is "3foo" (or maybe "foo3", there's no guarantee form the spec either way)
有几种方法可以解决这个问题。首先,由于这种胡说八道,你真的不应该在数组对象上使用 for-in。但是,如果出于某种原因必须这样做,则应始终使用hasOwnProperty()
过滤器保护 for-in 循环,如下所示:
var output = "";
for (i in arr) { //arr from the previous code block
if (arr.hasOwnProperty(i)) {
output += i;
}
}
output; //is "3"
同样,不能保证在 for-in 上订购。因此,如果arr
是[1,1,1]
,您可能会得到output
as "201"
(尽管不太可能)。
另一种选择是尝试通过使用 ES5 的功能(如果存在)来保护自己免受其他人的错误编码,通过将它们设置为不可枚举来保护对象级别的原型属性。你会这样做:
var foo = (function() { /* do something */ });
if(typeof Object.defineProperty === "function") { //If ES5
Object.defineProperty(Array.prototype, "foo", {
value: foo,
enumerable: false //make it not enumerable
});
} else { //For older browsers
Array.prototype.foo = foo;
}
var arr = [], output = "";
arr[3] = true;
for(i in arr) { //Seriously, don't do this.
output += i;
}
output; //is "3"
我不能过分强调对数组进行 for-in 是一个坏主意。事实上,在几乎所有情况下,我都倾向于避免使用 for-in,因为你永远不知道外面是否有人想成为一个混蛋,并将其扔到他们的代码中间:
Object.prototype.ponies = "Ponies!";