关于javascript:为什么indexOf不能在IE8阵列上运行?

Why doesn't indexOf work on an array IE8?

下面的功能在Opera、Firefox和Chrome上运行良好。然而,在IE8中,它在if ( allowed.indexOf(ext[1]) == -1)部分失败。

有人知道为什么吗?有什么明显的错误吗?

1
2
3
4
5
6
7
8
9
10
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!');
    }
}


IE9之前的IE版本没有用于数组的.indexOf()函数,要定义确切的规范版本,请在尝试使用它之前运行此函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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或更低。


如果您使用的是jquery,那么可以改用$.inarray()。


如果您正在使用jquery,并且希望继续使用indexof而不担心兼容性问题,那么可以这样做:

1
2
3
4
5
if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(val) {
        return jQuery.inArray(val, this);
    };
}

当您想继续使用indexOf时,这是很有用的,但当它不可用时,提供一个回退。


要获得真正彻底的解释和解决方法,不仅要了解indexof,还要了解IE中缺少的其他数组函数,请查看Internet Explorer中的stackoverflow问题修复javascript数组函数(indexof、foreach等)。


如果你想用的话,请小心点。我刚刚发现,$.inarray只适用于"array",而不是字符串。这就是为什么这个函数在IE8中不起作用的原因!

jquery API让人困惑

The $.inArray() method is similar to JavaScript's native .indexOf()
method in that it returns -1 when it doesn't find a match. If the
first element within the array matches value, $.inArray() returns 0

他们不应该说"相似"。因为indexof也支持"string"!


问题

ie<=8只是没有数组的indexOf()方法。

解决方案

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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;
    };
}

缩小:

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
    };
}