Cómo arreglar Array indexOf () en JavaScript para los navegadores Internet Explorer


295

Si ha trabajado con JavaScript por algún tiempo, sabe que Internet Explorer no implementa la función ECMAScript para Array.prototype.indexOf () [incluido Internet Explorer 8]. No es un gran problema, porque puede ampliar la funcionalidad de su página con el siguiente código.

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

¿Cuándo debo implementar esto?

¿Debo envolverlo en todas mis páginas con la siguiente verificación, que verifica si la función del prototipo existe y si no, continúe y extienda el prototipo de matriz?

if (!Array.prototype.indexOf) {

    // Implement function here

}

¿O comprueba el navegador y si es Internet Explorer, simplemente impleméntelo?

//Pseudo-code

if (browser == IE Style Browser) {

     // Implement function here

}

En realidad Array.prototype.indexOfno es parte de ECMA-262 / ECMAScript. Ver ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf Quizás estés pensando String.prototype.indexOf...
Crescent Fresh el

55
Es una extensión, no parte del estándar original. Sin embargo, debe implementarse como parte de Javascript 1.6 (que IE no puede hacer) developer.mozilla.org/en/New_in_JavaScript_1.6
Josh Stodola

1
@Josh: solo se refería a "IE no implementa la función ECMAScript ..."
Crescent Fresh el

44
Su implementación de Array.indexOfno tiene en cuenta los índices iniciales negativos. Vea la implementación
provisional de

3
He actualizado la pregunta para usar "===", porque me preocupa que la gente la copie con "==" y eso estaría mal, aparte de eso está bien. Ver la respuesta de Eli Grey.
joshcomley

Respuestas:


213

Hazlo asi...

if (!Array.prototype.indexOf) {

}

Según la compatibilidad recomendada por MDC .

En general, el código de detección del navegador es un gran no-no.


No tengo suficiente representante para editar la pregunta, pero siéntase libre de eliminar la jerga de ECMAScript y reemplazarla con la redacción adecuada. Gracias de nuevo
Bobby Borszich

12
Tenga cuidado si usa este tipo de detección. Otra biblioteca podría implementar esta función antes de probarla, y podría no cumplir con los estándares (el prototipo lo ha hecho hace un tiempo). Si estuviera trabajando en un ambiente hostil (un montón de otros codificadores que utilizan una gran cantidad de distintas bibliotecas), yo no confiar en ninguno de estos ...
Pablo Cabrera

La columna "Vinculado" ---> es realmente útil. Me encanta la respuesta aquí: stackoverflow.com/questions/1744310/…
gordon el

¿Tiene que estar envuelto en cada archivo js?
rd22

¿Quién es MDC exactamente?
Ferrybig

141

Alternativamente, puede usar la función jQuery 1.2 inArray , que debería funcionar en todos los navegadores:

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

El 'indexOf' es código nativo (derecha), entonces ¿jQuery 'inArray ()' será tan rápido, como usar native cuando esté disponible y poly-fill cuando no?
Jeach

10
Ok, para responder mi propio comentario (arriba), lo acabo de implementar y en Chrome es tan rápido como cuando estaba usando 'indexOf ()', pero en IE 8 es muy, muy lento ... así que al menos sabemos que 'inArray ()' usa nativo cuando puede.
Jeach

78

El código completo sería este:

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

Para obtener una respuesta y un código realmente completos para esto, así como para otras funciones de matriz, consulte la pregunta sobre desbordamiento de pila. Cómo arreglar las funciones de matriz de JavaScript en Internet Explorer (indexOf, forEach, etc.) .


2
gracias por tener todo el contenido Visito esta página con frecuencia cada vez que necesito indexOf multiplataforma en un nuevo proyecto, y su fragmento es el único con código completo. :) Esos pocos segundos realmente se suman cuando uno frecuenta esta página.
dylnmc


10

Debe verificar si no está definido usando if (!Array.prototype.indexOf).

Además, su implementación de indexOfno es correcta. Debe usar en ===lugar de ==en su if (this[i] == obj)declaración, de lo contrario [4,"5"].indexOf(5)sería 1 de acuerdo con su implementación, lo cual es incorrecto.

Le recomiendo que use la implementación en MDC .


9

Hay una solución oficial de Mozilla: 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;
        };
    }
})();

1
Solo siendo pedante, pero MDN no es solo Mozilla. Es un proyecto impulsado por la comunidad que contiene personal de Mozilla pero también voluntarios, cualquiera puede unirse y contribuir.
ste2425


2

Esta fue mi implementación. Básicamente, agregue esto antes que cualquier otro script en la página. es decir, en su maestro para una solución global para Internet Explorer 8. También agregué la función de recorte que parece usarse en una gran cantidad de marcos.

<!--[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]-->

2

esto funciona para mi.

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

1

Con el Underscore.js

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.