Bobby Borszich
Bobby Borszich

Reputation: 11767

How to fix Array indexOf() in JavaScript for Internet Explorer browsers

If you have worked with JavaScript at any length you are aware that Internet Explorer does not implement the ECMAScript function for Array.prototype.indexOf() [including Internet Explorer 8]. It is not a huge problem, because you can extend the functionality on your page with the following code.

Array.prototype.indexOf = function(obj, start) {
     for (var i = (start || 0), j = this.length; i < j; i++) {
         if (this[i] === obj) { return i; }
     }
     return -1;
}

When should I implement this?

Should I wrap it on all my pages with the following check, which checks if the prototype function exists and if not, go ahead and extend the Array prototype?

if (!Array.prototype.indexOf) {

    // Implement function here

}

Or do browser check and if it is Internet Explorer then just implement it?

//Pseudo-code

if (browser == IE Style Browser) {

     // Implement function here

}

Upvotes: 300

Views: 180070

Answers (10)

Allen Wong
Allen Wong

Reputation: 1433

it works for me.

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

Upvotes: 2

Will V King
Will V King

Reputation: 131

There is Mozilla official solution: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

(function() {
    /**Array*/
    // Production steps of ECMA-262, Edition 5, 15.4.4.14
    // Reference: http://es5.github.io/#x15.4.4.14
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(searchElement, fromIndex) {
            var k;
            // 1. Let O be the result of calling ToObject passing
            //    the this value as the argument.
            if (null === this || undefined === this) {
                throw new TypeError('"this" is null or not defined');
            }
            var O = Object(this);
            // 2. Let lenValue be the result of calling the Get
            //    internal method of O with the argument "length".
            // 3. Let len be ToUint32(lenValue).
            var len = O.length >>> 0;
            // 4. If len is 0, return -1.
            if (len === 0) {
                return -1;
            }
            // 5. If argument fromIndex was passed let n be
            //    ToInteger(fromIndex); else let n be 0.
            var n = +fromIndex || 0;
            if (Math.abs(n) === Infinity) {
                n = 0;
            }
            // 6. If n >= len, return -1.
            if (n >= len) {
                return -1;
            }
            // 7. If n >= 0, then Let k be n.
            // 8. Else, n<0, Let k be len - abs(n).
            //    If k is less than 0, then let k be 0.
            k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
            // 9. Repeat, while k < len
            while (k < len) {
                // a. Let Pk be ToString(k).
                //   This is implicit for LHS operands of the in operator
                // b. Let kPresent be the result of calling the
                //    HasProperty internal method of O with argument Pk.
                //   This step can be combined with c
                // c. If kPresent is true, then
                //    i.  Let elementK be the result of calling the Get
                //        internal method of O with the argument ToString(k).
                //   ii.  Let same be the result of applying the
                //        Strict Equality Comparison Algorithm to
                //        searchElement and elementK.
                //  iii.  If same is true, return k.
                if (k in O && O[k] === searchElement) {
                    return k;
                }
                k++;
            }
            return -1;
        };
    }
})();

Upvotes: 9

srikanth_yarram
srikanth_yarram

Reputation: 957

With the Underscore.js

var arr=['a','a1','b'] _.filter(arr, function(a){ return a.indexOf('a') > -1; })

Upvotes: 1

Glennweb
Glennweb

Reputation: 139

This was my implementation. Essentially, add this before any other scripts on the page. i.e. in your master for a global solution for Internet Explorer 8. I also added in the trim function which seems to be used in allot of frameworks.

<!--[if lte IE 8]>
<script>
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(obj, start) {
            for (var i = (start || 0), j = this.length; i < j; i++) {
                if (this[i] === obj) {
                    return i;
                }
            }
            return -1;
        };
    }

    if(typeof String.prototype.trim !== 'function') {
        String.prototype.trim = function() {
            return this.replace(/^\s+|\s+$/g, '');
        };
    };
</script>
<![endif]-->

Upvotes: 2

Luis Perez
Luis Perez

Reputation: 28120

The full code then would be this:

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

For a really thorough answer and code to this as well as other array functions check out Stack Overflow question Fixing JavaScript Array functions in Internet Explorer (indexOf, forEach, etc.).

Upvotes: 80

Moses Lee
Moses Lee

Reputation: 1544

Alternatively, you could use the jQuery 1.2 inArray function, which should work across browsers:

jQuery.inArray( value, array [, fromIndex ] )

Upvotes: 142

scotta7exander
scotta7exander

Reputation: 383

The underscore.js library has an indexOf function you can use instead:

_.indexOf([1, 2, 3], 2)

Upvotes: 16

Josh Mc
Josh Mc

Reputation: 10224

I would recommend this to anyone looking for missing functionality:

http://code.google.com/p/ddr-ecma5/

It brings in most of the missing ecma5 functionality to older browers :)

Upvotes: 5

Eli Grey
Eli Grey

Reputation: 35860

You should check if it's not defined using if (!Array.prototype.indexOf).

Also, your implementation of indexOf is not correct. You must use === instead of == in your if (this[i] == obj) statement, otherwise [4,"5"].indexOf(5) would be 1 according to your implementation, which is incorrect.

I recommend you use the implementation on MDC.

Upvotes: 10

Josh Stodola
Josh Stodola

Reputation: 82483

Do it like this...

if (!Array.prototype.indexOf) {

}

As recommended compatibility by MDC.

In general, browser detection code is a big no-no.

Upvotes: 215

Related Questions