在分配Array.prototype.indexOf之后导致此错误的原因是什么?

时间:2009-04-23 05:39:07

标签: javascript internet-explorer

当我能够使用最少量的代码重现错误时,我感到很惊讶。请注意,在此极简主义示例中,未调用Array.indexOf。另请注意,我已经尝试了几种不同的indexOf实现,包括stackoverflow.com中的几种。

该错误是,当在IE中执行for ... in时,会显示三个警报:“indexOf”,“0”和“1”。在FF中,正如人们所预料的那样,只出现两个(“0”,“1”)。

<html>
<body onLoad="test();">
<script language="javascript">
   var testArray = ['Foo', 'Bar'];

   if(!Array.prototype.indexOf) {
      Array.prototype.indexOf = function (obj, fromIndex) {
         if (fromIndex == null) {
            fromIndex = 0;
         } else if (fromIndex < 0) {
            fromIndex = Math.max(0, this.length + fromIndex);
         }
         for (var i = fromIndex, j = this.length; i < j; i++) {
            if (this[i] === obj)
               return i;
         }
         return -1;
      };
   }

   function test() {
      var i;

      for(i in testArray) {
         alert(i);
      }
   }
</script>
</body>
</html>

任何人都能解释一下吗?我已经改变了我的代码以使用while所以我不是在枪口下,但这个真的让我感到难过。它让我想起c。

中的内存溢出错误

2 个答案:

答案 0 :(得分:4)

请参阅Yahoo!上的“for in Intrigue”用户界面博客。

您的代码在Firefox中按预期工作的原因是因为您尚未在Firefox中添加自己的indexOf方法。 for in循环遍历对象原型链中的所有键,包括您添加的indexOf方法。 Douglas Crockford建议采用以下解决方案:

for (var p in testArray) {
    if (testArray.hasOwnProperty(p)) {
        alert(testArray[i]);
    }
}

或者,您可以过滤掉功能:

for (var p in testArray) {
    if (typeof testArray[p] !== "function") {
        alert(testArray[i]);
    }
}

另外,正如“nickf”指出的那样,最好不要使用for in循环来迭代数组。 for in循环用于迭代对象中的键。

史蒂夫

答案 1 :(得分:4)

for .. in用于循环访问对象属性,绝对不是数组。

坚持标准:

for (var i = 0, l = myArray.length; i < l; ++i) { .. }

Mozilla Developer Centre的更多信息:

  

for...in循环不会迭代内置属性。这些包括对象的所有内置方法,例如String的indexOf方法或Object的toString方法。但是,循环将遍历所有用户定义的属性(包括任何覆盖内置属性的属性)。

     

尽管使用它作为迭代数组的方法可能很诱人,但这是一个坏主意。除了数组元素之外,for ... in语句还迭代用户定义的属性,因此如果修改数组的非整数或非正属性(例如,通过向其添加“foo”属性,或者甚至通过添加方法或属性到Array.prototype),for ... in语句将返回除数字索引之外的用户定义属性的名称。