对象/数组和循环的原型

时间:2012-09-06 17:24:34

标签: javascript prototype

今天出现了一个奇怪的错误。在我们的应用程序中,在一个文件中,所有对象都附加了一个函数,就好像它们是原型一样。我们没有对我们的数组进行原型设计,但是我已经研究了其他数组和对象都有原型的东西,当你做了一个for(这个)循环时,原型将作为项目包含在内,我们必须对它们进行过滤。所以,两部分问题:

  1. 如果您对数组进行原型设计,那么索引会增加+#原型吗?因此,如果array(a,b,c)有array.prototype.function(),它的索引计数是3还是4?

  2. 这应该发生吗?

  3. 我们认为我们拥有的jquery插件之一就是邪恶的。

3 个答案:

答案 0 :(得分:2)

虽然数组是对象,因此可以有多个属性,但只有整数属性才会计入array本身。

var a = [];
alert(a.length); // 0
a.foo = "Ha";
alert(a.length); // 0
a[1] = 10;
alert(a.length); // 1

Array.prototype.shuffle = function() { ... }
alert(a.length); // 1

虽然不建议使用for ... in来处理数组,但有些人仍然这样做。 for ... in会找到fooshuffle

答案 1 :(得分:2)

通过“索引计数”我假设你的意思是length属性。在这种情况下,你的第一个问题的答案是“不”。 length属性与数组的最高数字索引相关联。因此,例如,如果您有以下代码,arr.length将是4

var arr = [];
arr[3] = true;
arr.length; //is 4

但是,你提到了for-in循环,它在这种情况下有奇怪的行为。如果我们在arr(从上面)执行for-in,我们会得到以下结果:

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"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!";

答案 2 :(得分:1)

如果你避免使用for (var i in array)来迭代你的数组并仅通过从0到array.length - 1的数字索引来迭代它们,那么如果有人在数组原型中添加了某些东西你就不会有问题。这正是您应该避免使用for/in技术迭代数组的原因。

一些安全的方法来迭代数组,无论有多少属性或方法被添加到数组或数组原型中:

for (var i = 0, len = array.length; i < len; i++) {
    // access array[i] here
}

var i = 0, len = array.length;
while (i < len) {
    // access array[i] here
    i++;
}