为什么indexOf在数组IE8上不起作用?


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!');
    }
}

5
好问题,好答案。感谢您给我我所需要的。
Hardwareguy

Answers:


488

IE9之前的IE版本没有.indexOf()Array 的功能,以定义确切的规范版本,请在尝试使用它之前运行此功能:

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

这是MDN的版本,在Firefox / SpiderMonkey中使用。在其他情况下(例如IE),它会.indexOf()在丢失的情况下添加……基本上是IE8或以下版本。


2
请注意,如果您(或您使用的库)使用for / in语法枚举数组(例如,for(idx in arrayname)stmt;),则也会枚举此方法。这是因为内置属性不是由for / in枚举的,而是由用户定义的。
西班牙

5
@Mike-这是一个不同的问题...您不应该使用for...in循环来迭代数组,而应 仅将其用于枚举
尼克·克拉弗

3
@Mike-出于更多原因,您要遍历数组。例如,在浏览器中以正确的顺序获取结果。for..in在数组上使用只会引起问题,这不仅是一个约定,而且是意外使用和不正确的用法。顺序和键都没有完全指定,它们与实现有关...例如,IE将按添加顺序而不是按索引枚举数组项。但是,您可以正确地进行迭代,通过索引访问。
尼克·克雷弗

1
这说明了枚举元素与使用索引进行迭代之间的区别。这就是为什么我们有两个概念。您可以枚举链接列表中的值,也可以爬网链接列表并将值从一个返回到下一个。一个是数学概念,一个是程序指令。
jcolebrand

1
@Pointy是的!而且由于许多人在搜索“为什么indexOf在数组IE8上不起作用?” 可能对js而言,其WRT的复杂程度较低,将其作为答案的必然结果可能会有所帮助。如果每个人都已经对规范和实现之间的差异有了深刻的了解,那么就不会有诸如此类的线程。@Nick您对正确性有很强的假设。有许多操作的顺序无关紧要(例如,设置差异)。此外,原始注释未提及按索引顺序进行枚举,只是for / in包括用户定义fn。
西班牙

152

如果使用的是jQuery,则可以改用$ .inArray()


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

17

如果您使用的是jQuery并希望继续使用indexOf而不用担心兼容性问题,则可以执行以下操作:

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(val) {
        return jQuery.inArray(val, this);
    };
}

当您想继续使用时indexOf提供帮助,但在不可用时提供备用。


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


5

如果要使用$ .inArray,请小心。我刚刚发现$ .inArray仅适用于“ Array”,不适用于String。这就是为什么此功能无法在IE8中使用的原因!

jQuery API令人困惑

$ .inArray()方法类似于JavaScript的本机.indexOf()方法,因为它找不到匹配项时返回-1。如果数组中的第一个元素匹配值,则$ .inArray()返回0

->他们不应该说“类似”。由于indexOf支持“字符串”也!


16
叫做inArray。这似乎很明确地仅适用于数组。这就是为什么它“类似于”而不是“相同于”的原因。
tandrewnichols 2014年

好注意 有趣的事实是indexOf,在IE中完全可以找到String对象,而indexOf在IE <= 8中找不到Array原型
。– adi518

您将其绑定到数组原型,因此它不会影响字符串。
kagronick

3

问题

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


解决方案

如果您需要indexOfIE <= 8,则应考虑使用以下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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.