JS "for (var key in arr)" > 抛出我自己的 Array.prototypes,但不是固有的。为什么?

JS "for (var key in arr)" > throws my own Array.prototypes, but not the inherent ones. Why?

我不小心使用了像

这样的迭代
for (var key in arr)
{
    alert(key);
}

得到的输出引发了一些问题。 (我想遍历 JSON,所以我使用了 'key' - 在这种情况下,索引的 'i' 更合适,毫无疑问:-)

第一个输出是索引(如“0”、“1”等)——仍然没有问题——但最后它抛出了我的 Array.prototypes 的名字,我在代码的其他地方声明了.原型如

Array.prototype.lastIndex = function(){
    return this.length - 1;
}

它只抛出 'lastIndex'。

我不明白的是:我自己的非固有原型是否与 JS 固有原型(如 splice()、slice() ...)不同?

并且:为什么它会抛出它们?它们是 Array.prototype 的一部分,但不是特定数组对象的一部分!?

提前致谢!

任何数组实例 继承 来自 Array.prototype。因此,对原型的任何更改也会反映在这些数组 instances 中。

如果您希望它只保留给 arr,您可以将函数 lastIndex 附加到它,因此其他数组 instances 将无法获取受影响。

所以它出现在for..in循环中,循环遍历可枚举的属性,因为lastIndex是一个可枚举的属性。

  1. 当您将 属性 附加到对象时,默认情况下,属性 将为 enumerable

  2. 如果 属性 是可枚举的,for..in 将拾取它。

所以,当你用for..in迭代一个数组对象时,它首先给出当前对象中的所有可枚举属性。然后,它沿原型链向上,给出相应对象的所有可枚举属性。因此,在您的情况下,它沿着链上升并在 Array 的原型中找到一个名为 lastIndex 的可枚举 属性,并将其包含在迭代中。

如果用enumerable: false定义,像这样

Object.defineProperty(Array.prototype, 'lastIndex', {
    value: function() {
        return this.length - 1;
    },
    enumerable: false
});

它不会出现在 for..in 次迭代中。引用 MDN documentation for enumerable attribute,

The enumerable property attribute defines whether the property shows up in a for...in loop and Object.keys() or not.

注: Always use normal for loops for array iterations.