为什么在IE8中数组的indexOf方法无法使用?

294

以下的函数在 Opera、Firefox 和 Chrome 上都能正常工作。但是在 IE8 上,if ( allowed.indexOf(ext[1]) == -1) 部分会出现问题。

有人知道为什么吗?是否有任何明显的错误?

function CheckMe() {
    var allowed = new Array('docx','xls','xlsx', 'mp3', 'mp4', '3gp', 'sis', 'sisx', 'mp3', 'wav', 'mid', 'amr', 'jpg', 'gif', 'png', 'jpeg', 'txt', 'pdf', 'doc', 'rtf', 'thm', 'rar', 'zip', 'htm', 'html', 'css', 'swf', 'jar', 'nth', 'aac', 'cab', 'wgz');
    var fileinput=document.getElementById('f');
    var ext = fileinput.value.toLowerCase().split('.');
    if ( allowed.indexOf(ext[1]) == -1) 
    {
        document.getElementById('uploadsec').innerHTML = document.getElementById('uploadsec').innerHTML;
        alert('This file type is not allowed!');
    }
}
7个回答

488

IE9之前的版本不支持Array的.indexOf()函数,为了定义准确的规范版本,在尝试使用它之前,请先运行以下代码:

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;
  };
}

这是在Firefox/SpiderMonkey中使用的版本from MDN。 在其他情况下,例如IE,它将添加.indexOf(),以防缺失... 基本上是目前的IE8或更低版本。


2
请注意,如果您(或您使用的库)使用for/in语法来枚举数组(例如:for(idx in arrayname)stmt;),那么这种方法也会被枚举。这是因为内置属性不会被for/in枚举,但用户定义的属性会被枚举。 - Spain Train
5
@Mike - 这是一个不同的问题...你不应该使用for...in循环来遍历数组,它只应该用于枚举 - Nick Craver
3
@Mike - 你遍历数组的原因可能不止一个,例如确保在不同浏览器下按正确的顺序获取结果。 使用for..in遍历数组只会引起问题,这不仅是一种约定,而且是一种错误的用法。 数组中的顺序和键都没有被完全指定,它们是依赖于具体实现的......例如,IE将按添加的顺序枚举数组项,而不是按其索引。 但是,您可以通过访问索引来正确地迭代 - Nick Craver
1
这就说明了枚举元素和使用索引迭代之间的区别。这也是为什么我们有这两个概念的原因。你可以枚举链表中的值,或者你可以遍历链表并返回从一个到下一个的值。一个是数学概念,一个是过程指令。 - jcolebrand
1
@Pointy 是的!由于许多人在js方面的技术水平较低,因此搜索“为什么indexOf在数组IE8上不起作用?”可能会有所帮助,将其作为答案的推论指出。如果每个人都已经深入了解规范和实现之间的差异,这样的线程就不会存在。@Nick 您对正确性做出了强烈的假设。有许多操作顺序并不重要(例如,集合差异)。此外,原始评论没有提到按索引顺序枚举,只是说/包括用户定义的fn。 - Spain Train
显示剩余3条评论

153
如果您正在使用jQuery,可以使用$.inArray()代替。

7
我同意这更有用。这是使用jQuery的主要原因之一——它在很大程度上缓解了跨浏览器不兼容性问题。 - cw24

17
如果您正在使用 jQuery 并且希望继续使用 indexOf 而不必担心兼容性问题,可以这样做:
if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(val) {
        return jQuery.inArray(val, this);
    };
}

当您想继续使用indexOf但在其不可用时提供备用选项时,这很有帮助。


是的,可能是因为他没有包含jQuery ¯_(ツ)_/¯ 这是有效的语法。 - user9016207

10

5
请注意使用$.inArray函数时要小心,它只能用于"数组",而不能用于字符串。因此,这个函数在IE8中将无法工作!
jQuery API有些令人困惑。
引用: $.inArray()方法类似于JavaScript本身的.indexOf()方法,当没有匹配项时返回-1。如果数组中的第一个元素与值匹配,则$.inArray()返回0。
-->他们不应该说它是“类似的”。因为indexOf也支持“字符串”!

16
它被称为 inArray。这似乎明确地适用于数组。这就是为什么它是“类似于”,而不是“相同于”的原因。 - tandrewnichols
好的注意事项。有趣的事实是,在String对象中的indexOf在IE中完全被找到,而在Array原型中的indexOf在IE <= 8中没有被找到。 - adi518
你将其绑定到数组原型上,因此不会影响字符串。 - kagronick

3

问题

IE<=8没有数组的indexOf()方法。


解决方案

如果您需要在IE<=8中使用indexOf,您应该考虑使用以下polyfill,这是MDN推荐的

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(searchElement, fromIndex) {
        var k;
        if (this == null) {
            throw new TypeError('"this" is null or not defined');
        }
        var o = Object(this);
        var len = o.length >>> 0;
        if (len === 0) {
            return -1;
        }
        var n = +fromIndex || 0;
        if (Math.abs(n) === Infinity) {
            n = 0;
        }
        if (n >= len) {
            return -1;
        }
        k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
        while (k < len) {
            if (k in o && o[k] === searchElement) {
                return k;
            }
            k++;
        }
        return -1;
    };
}

压缩后的代码:

Array.prototype.indexOf||(Array.prototype.indexOf=function(r,t){var n;if(null==this)throw new TypeError('"this" is null or not defined');var e=Object(this),i=e.length>>>0;if(0===i)return-1;var a=+t||0;if(Math.abs(a)===1/0&&(a=0),a>=i)return-1;for(n=Math.max(a>=0?a:i-Math.abs(a),0);i>n;){if(n in e&&e[n]===r)return n;n++}return-1});

1

如果函数不存在,您可以使用此方法进行替换:

<script>
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;
    };
}
</script>

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