Internet Explorer 的 Array indexOf 实现

3

有很多解决方案可以将indexOf实现添加到Array原型中,以便在Internet Explorer下运行,但是我遇到了一个问题,到目前为止似乎没有任何地方提到过。

使用经过广泛认可的MDC实现,我现在有以下有问题的代码:

// indexOf support for IE (from MDC)
if (!Array.prototype.indexOf)
{
    Array.prototype.indexOf = function(elt /*, from*/)   
    {
        var len = this.length >>> 0;

        var from = Number(arguments[1]) || 0;
        from = (from < 0) ? Math.ceil(from) : Math.floor(from);
        if (from < 0)
            from += len;

        for (; from < len; from++)
        {
            if (from in this && this[from] === elt)  
                return from;
        }
        return -1;
    };
}

var i = [1,2,3,4];

for (j in i)
{
    alert(i[j]);
}

我希望收到4个警报,每个警报包含数组中的一个元素。 在Firefox和Chrome中,我看到的正是这样,然而在IE8中,我会得到一个包含indexOf函数代码的额外警报。
有什么方法可以避免这种情况?
3个回答

5
这是因为在IE中,由于该方法不存在,它被添加到Array.prototype中,并且仍然可枚举。
对于处理数组(以及一般的类似数组的对象),我不建议使用for...in语句。
为什么?
  • for...in语句用于枚举对象属性。
  • for...in语句会遍历原型链,正如你所注意到的。
  • 迭代顺序可能是任意的,迭代数组可能不按数值顺序访问元素。
最简单的方法是使用普通的for循环:
for (var j = 0; j < i.length; j++) {
    alert(i[j]);
}

参见:


感谢提供的信息。我只希望IE能像FF和Chrome一样处理那些东西。而将for...in重写为for循环并不是一个真正的选择,遗留代码可能会让人头疼。 - Daemon

3
这是因为您编辑了Array.prototype,因此创建的任何数组都会继承自定义的VISIBLE方法indexOf,而"in"命令可以看到它。
在JavaScript中,for..in结构不像PHP的foreach一样只迭代数组中的所有项,而且还迭代数组对象可能具有的所有方法和属性(JavaScript中的数组实际上是“伪装”的对象)。原生方法对for..in结构不可见,但所有自定义添加都不可见。
在您的示例中,任何数组都将如下所示:
Array:
- [0] value
- [1] value
- [2] value
- ..
- [N] value
- [IndexOf] value

为了避免继承的非期望方法和属性,可以使用方法hasOwnProperty():
for (j in j){
    if(i.hasOwnProperty(j){
        alert(i[j])
    }
}

hasOwnProperty用于检查一个属性是否是对象本身的属性,而非继承自原型链。这样可以确保只有需要的值被传递。


1
惯例是在对象(枚举)上使用 for..in,在数组(迭代)上使用普通的 for。请参见CMS的答案。 - Justin Johnson
1
for..in并不是迭代数组的最合适结构,特别是考虑到迭代顺序不能保证,但有时确实是就地进行的。 - Andris
感谢提供的信息。我只希望IE能像FF和Chrome一样处理那些东西。而将for...in重写为for循环并不是一个真正的选择,遗留代码可能会让人头疼。 - Daemon

0

你能试着添加一下吗:

for (j in i) {
    if (i.hasOwnProperty(j)) { 
        alert(j); 
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接