Why doesn't indexOf work on an array IE8?
Asked Answered
C

7

294

The below function works fine on Opera, Firefox and Chrome. However, in IE8 it fails on the if ( allowed.indexOf(ext[1]) == -1) part.

Does anyone know why? Is there any obvious mistake?

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!');
    }
}
Changeup answered 2/9, 2010 at 16:33 Comment(0)
O
488

Versions of IE before IE9 don't have an .indexOf() function for Array, to define the exact spec version, run this before trying to use it:

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

This is the version from MDN, used in Firefox/SpiderMonkey. In other cases such as IE, it'll add .indexOf() in the case it's missing... basically IE8 or below at this point.

Orlandoorlanta answered 2/9, 2010 at 16:38 Comment(8)
Ah OK, I didn't spot the links.Klemm
Note the caveat that if you (or libraries you use) use the for/in syntax to enumerate arrays (ex. for(idx in arrayname)stmt;) that this method will be enumerated as well. This is because built-in properties are not enumerated by for/in but user-defined ones are.Sycamine
@Mike - That's a different problem...you shouldn't be using a for...in loop to iterate an array, it should be used for enumeration only.Orlandoorlanta
It is a related problem. Enumeration is the listing of elements in a set. Iteration, with an array index as the mutable state, is a common method of enumeration. When available, so is for/in. It is a peculiarity of the ECMA specification that these two methods yield different enumerations of the (seemingly) same set under certain conditions. It is thus convention to use iteration to find the enumeration that excludes unwanted elements, such as functions. This convention is noteworthy for those using the above answer because previously working code that did not follow convention may fail.Sycamine
@Mike - You iterate over an array for more reasons for that..like getting your results in the right order across browsers. Using for..in on an array will only cause issues, it's not just a convention..it's unintended usage and an incorrect one. The order and keys are both not completely specified, they're implementation dependent...for example IE will enumerate the array items in the order they were added, not by their index. However you can iterate correctly, accessing by index.Orlandoorlanta
And that illustrates the difference between enumerating the elements and using an index to iterate. Which is why we have both concepts. You can enumerate the values in a linked list, or you can crawl the linked list and return the values from one to the next. One is a mathematical concept, one is a procedural instruction.Gentoo
Using for ... in on an array object is just asking for trouble, and virtually 100% of the times I've seen it done (here on SO and elsewhere) it was being done by somebody who didn't know any better, and not by someone with deep understanding of the actual semantics.Gigahertz
@Gigahertz Yes! And since many searching for "Why doesn't indexOf work on an array IE8?" may be at a lower sophistication level WRT to js, it may be helpful to point this out as a corollary to the answer. If everyone already had a deep understanding of the spec and differences between implementations, threads such as these wouldn't exist. @Nick You make strong assumptions about correctness. There are many operations for which order does not matter (e.g., set difference.) Also, the original comment made no mention of enumerating in index sequence, just that for/in includes user def fn's.Sycamine
D
153

If you're using jQuery, you can use $.inArray() instead.

Dipteran answered 18/1, 2012 at 16:56 Comment(1)
I agree that this is more useful. That is one of the main reasons for using JQuery - it does a lot to alleviate cross browser incompatibilities.Porkpie
V
17

If you're using jQuery and want to keep using indexOf without worrying about compatibility issues, you can do this :

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

This is helpful when you want to keep using indexOf but provide a fallback when it's not available.

Vibrato answered 28/2, 2014 at 18:3 Comment(1)
Yes, probably because he didn't include jQuery ¯_(ツ)_/¯ It is valid syntax.Glazier
P
10

For a really thorough explanation and workaround, not only for indexOf but other array functions missing in IE check out the StackOverflow question Fixing JavaScript Array functions in Internet Explorer (indexOf, forEach, etc.)

Projection answered 11/1, 2012 at 2:40 Comment(0)
P
5

Please careful with $.inArray if you want to use it. I just found out that the $.inArray is only works with "Array", not with String. That's why this function will not working in IE8!

The jQuery API make confusion

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

--> They shouldn't say it "Similar". Since indexOf support "String" also!

Pouched answered 4/9, 2013 at 8:24 Comment(3)
It's called inArray. That seems pretty definitively to apply to arrays only. That's why it's "similar to" and not "identical to."Arapaima
Good note. The funny fact is indexOf in a String object is fully found in IE while indexOf in Array prototype is not found in IE <= 8.Racemose
You're binding it to the array prototype so its not going to affect strings.Exchequer
C
3

The problem

IE<=8 simply doesn't have an indexOf() method for arrays.


The solution

If you need indexOf in IE<=8, you should consider using the following polyfill, which is recommended at the 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;
    };
}

Minified :

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});
Cacology answered 21/2, 2016 at 17:43 Comment(0)
R
1

You can use this to replace the function if it doesn't exist:

<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>
Rare answered 23/2, 2015 at 17:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.