294

Si ha trabajado con JavaScript en cualquier longitud, sabe que Internet   Explorer no implementa la función ECMAScript para Array.prototype.indexOf() [incluyendo Internet   Explorer   8]. No es un gran problema, porque puede ampliar la funcionalidad en su página con el siguiente código.Cómo reparar Array indexOf() en JavaScript para navegadores Internet Explorer

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 comprobación, que comprueba si existe la función de prototipo y, en caso negativo, seguir ampliando el prototipo de matriz?

if (!Array.prototype.indexOf) { 

    // Implement function here 

} 

O hacer revisión del navegador y si se trata de Internet Explorer, a continuación   acaba de ponerlo en práctica?

//Pseudo-code 

if (browser == IE Style Browser) { 

    // Implement function here 

} 
+0

En realidad 'Array.prototype.indexOf' no es parte de ECMA-262/ECMAScript. Consulte http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf Quizás esté pensando 'String.prototype.indexOf' ... –

+5

Es una extensión, no parte del norma original. Sin embargo, debería implementarse como parte de Javascript 1.6 (que IE no puede hacer) https://developer.mozilla.org/en/New_in_JavaScript_1.6 –

+1

@Josh: solo se refería a "IE no implementa la función ECMAScript ... " –

Respuesta

212

hacerlo de esta manera ...

if (!Array.prototype.indexOf) { 

} 

Como recommended compatibility by MDC.

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

+0

No tengo suficiente reputación para editar la pregunta, pero siéntase libre de eliminar la jerga ECMAScript y reemplace con la redacción adecuada. Gracias otra vez –

+11

Tenga cuidado si usa este tipo de detección. Otra biblioteca podría implementar esta función antes de probarla, y podría no ser compatible con los estándares (el prototipo lo ha hecho hace un tiempo). Si estuviera trabajando en un entorno hostil (muchos otros codificadores que utilizan muchas bibliotecas distintas), no confiaría en ninguno de estos ... –

+0

¡La columna "Vinculada" ---> es realmente útil! Me encanta la respuesta aquí: http://stackoverflow.com/questions/1744310/how-to-fix-array-indexof-in-javascript-for-internet-explorer-browsers?lq=1 – gordon

10

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

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

Te recomiendo que uses the implementation on MDC.

+1

En realidad, sería 1 ... –

140

Como alternativa, puede utilizar el jQuery 1.2 inArray function, que debería funcionar en todos los navegadores:

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

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

+10

Ok, para responder a mi propio comentario (arriba), simplemente lo implementé y en Chrome es tan rápido como cuando estaba usando 'indexOf()', pero en IE 8 es muy, muy lento ... al menos nosotros sabe que 'inArray()' usa nativo cuando puede. – Jeach

76

El código completo, entonces sería la siguiente:

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 una respuesta realmente a fondo y el código para esto como así como otras funciones de matriz, consulte la Pregunta de desbordamiento de pila Fixing JavaScript Array functions in Internet Explorer (indexOf, forEach, etc.).

+1

gracias por solo tener todo. 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

14

La biblioteca underscore.js tiene una función indexOf puede utilizar en su lugar:

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

Esta respuesta evita [jugar con el prototipo de matriz] (http://stackoverflow.com/q/780422/425313) y delega en el índice nativo cuando está disponible. Me gusta. –

+0

Parece ser la forma más fácil si puede incluir guiones bajos o lodash – ChrisRich

5

lo recomendaría a cualquiera que busque una funcionalidad que falta:

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

Trae en la mayoría de la funcionalidad ecma5 faltante a los navegadores más antiguos :)

+0

** Aunque tendré en cuenta que he tenido problemas en IE7 con esta lib. –

1

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é en la función de recorte que parece ser utilizada en muchos 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]--> 
1

Con los Underscore.js

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

8

Hay 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

Simplemente 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

1

funciona para mí.

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