对象/数组和循环上的原型

prototypes on objects/arrays and loops

本文关键字:原型 循环 数组 对象      更新时间:2023-09-26

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

  1. 如果你为你的数组制作原型,索引会增加+#个原型吗?所以,如果数组(a,b,c)有array.protype.function(),它的索引计数是3还是4?

  2. 这种情况应该发生吗?

我们认为我们拥有的一个jquery插件是邪恶的。

我认为"index count"是指length属性。在这种情况下,第一个问题的答案是"否"。length属性与数组的最高数字索引绑定。例如,如果您有以下代码,arr.length将是4:

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

然而,您提到了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

然而,它们确实会影响内循环(在正常情况下):

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对象,因为这是无稽之谈。但是,如果出于某种原因必须这样做,您应该始终使用hasOwnProperty()过滤器来保护for in loop,如下所示:

var output = "";
for (i in arr) { //arr from the previous code block
    if (arr.hasOwnProperty(i)) {
        output += i;
    }
} 
output; //is "3"

同样,不能保证在中的上订购

另一种选择是,通过使用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,因为你永远不知道是否有人想成为一个混蛋,并会把它扔到他们的代码中间:

Object.prototype.ponies = "Ponies!";

尽管数组是对象,因此可以有多个属性,但只有整数属性计入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

如果您避免使用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++;
}