2010-05-07 7 views
136

Como se detalla elsewhere, y aparentemente conocido, Internet Explorer (definitivamente la versión 7, y en algunos casos, la versión 8) no implementa funciones clave, en particular en Array (como forEach, indexOf, etc.).Fijación de funciones de matriz de JavaScript en Internet Explorer (indexOf, forEach, etc.)

Hay una serie de soluciones aquí y allá, pero me gustaría doblar un conjunto correcto y canónico de implementaciones en nuestro sitio en lugar de copiar y pegar o piratear en nuestras propias implementaciones. He encontrado js-methods, que parece prometedor, pero pensé en publicar aquí para ver si otra biblioteca es más recomendada. Un par de criterios diversos:

  • La biblioteca debe ser sólo un no-funcionamiento para aquellas funciones que un navegador ya tiene implementaciones de (js-methods parece hacer muy bien aquí).
  • No GPL, por favor, aunque LGPL es aceptable.

Respuesta

218

Muchos utilizan las implementaciones de respaldo de MDC (por ejemplo, para indexOf). Por lo general, cumplen rigurosamente con los estándares, incluso hasta el punto de verificar explícitamente los tipos de todos los argumentos.

Lamentablemente, aunque es evidente que los autores consideran que este código es trivial y de libre uso, no parece haber una concesión de licencia explícita para poner esto por escrito. El wiki en su conjunto es CC Attribution-ShareAlike, si es una licencia aceptable (aunque CC no está diseñado para código como tal).

js-methods se ve bien en general, pero no cumple con los estándares sobre cómo deben ser las funciones (por ejemplo, elementos de lista indefinidos, funciones que modifican la lista). También está lleno de otros métodos aleatorios no estándar, incluidos algunos dudosos como los trozos de etiqueta dudosos y el códec UTF-8 incompleto (que también es un poco innecesario dado el truco unescape(encodeURIComponent)).

Por lo que vale, esto es lo que uso (que por este medio lanzo al dominio público, si se puede decir que es susceptible de derechos de autor). Es un poco más corto que las versiones de MDC, ya que no intenta escribir-oler que no has hecho algo tonto como pasar devoluciones de llamada no funcionales o índices no enteros, pero aparte de eso, intenta ser compatible con los estándares. (Quiero saber si me he perdido nada. ;-))

'use strict'; 

// Add ECMA262-5 method binding if not supported natively 
// 
if (!('bind' in Function.prototype)) { 
    Function.prototype.bind= function(owner) { 
     var that= this; 
     if (arguments.length<=1) { 
      return function() { 
       return that.apply(owner, arguments); 
      }; 
     } else { 
      var args= Array.prototype.slice.call(arguments, 1); 
      return function() { 
       return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments))); 
      }; 
     } 
    }; 
} 

// Add ECMA262-5 string trim if not supported natively 
// 
if (!('trim' in String.prototype)) { 
    String.prototype.trim= function() { 
     return this.replace(/^\s+/, '').replace(/\s+$/, ''); 
    }; 
} 

// Add ECMA262-5 Array methods if not supported natively 
// 
if (!('indexOf' in Array.prototype)) { 
    Array.prototype.indexOf= function(find, i /*opt*/) { 
     if (i===undefined) i= 0; 
     if (i<0) i+= this.length; 
     if (i<0) i= 0; 
     for (var n= this.length; i<n; i++) 
      if (i in this && this[i]===find) 
       return i; 
     return -1; 
    }; 
} 
if (!('lastIndexOf' in Array.prototype)) { 
    Array.prototype.lastIndexOf= function(find, i /*opt*/) { 
     if (i===undefined) i= this.length-1; 
     if (i<0) i+= this.length; 
     if (i>this.length-1) i= this.length-1; 
     for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */ 
      if (i in this && this[i]===find) 
       return i; 
     return -1; 
    }; 
} 
if (!('forEach' in Array.prototype)) { 
    Array.prototype.forEach= function(action, that /*opt*/) { 
     for (var i= 0, n= this.length; i<n; i++) 
      if (i in this) 
       action.call(that, this[i], i, this); 
    }; 
} 
if (!('map' in Array.prototype)) { 
    Array.prototype.map= function(mapper, that /*opt*/) { 
     var other= new Array(this.length); 
     for (var i= 0, n= this.length; i<n; i++) 
      if (i in this) 
       other[i]= mapper.call(that, this[i], i, this); 
     return other; 
    }; 
} 
if (!('filter' in Array.prototype)) { 
    Array.prototype.filter= function(filter, that /*opt*/) { 
     var other= [], v; 
     for (var i=0, n= this.length; i<n; i++) 
      if (i in this && filter.call(that, v= this[i], i, this)) 
       other.push(v); 
     return other; 
    }; 
} 
if (!('every' in Array.prototype)) { 
    Array.prototype.every= function(tester, that /*opt*/) { 
     for (var i= 0, n= this.length; i<n; i++) 
      if (i in this && !tester.call(that, this[i], i, this)) 
       return false; 
     return true; 
    }; 
} 
if (!('some' in Array.prototype)) { 
    Array.prototype.some= function(tester, that /*opt*/) { 
     for (var i= 0, n= this.length; i<n; i++) 
      if (i in this && tester.call(that, this[i], i, this)) 
       return true; 
     return false; 
    }; 
} 

Otros métodos ECMA262-5 no se han aplicado aquí incluyen Matriz reduce/reduceRight, los JSON y los pocos nuevos Object métodos que se pueden implementar de forma fiable como JS funciona.

+5

Gracias por ese puntero - los otros enlaces que he visto en mozdev donde tales impls podrían encontrarse estaban obsoletos. FYI, el código está licenciado por MIT, como se especifica aquí: https://developer.mozilla.org/Project:Copyrights (tan bueno como se puede obtener! :-) – cemerick

+1

Curiosamente, si hago referencia a un archivo js que contiene todos las implicaciones MDC ECMA262-5 antes de jquery 1.4.2, jquery está roto, por ejemplo todos los selectores fallan, devolviendo nulo. Mover las impls de MDC después de jquery conduce al comportamiento esperado. Muy raro. – cemerick

+0

Eso * es * curioso! Veremos eso (¿tienes un caso de prueba?) ... No puedo pensar de inmediato por qué esto podría suceder, aunque lo que hace jQuery en la línea 72 parece sospechoso. – bobince

1

Con 'no implementar funciones clave', en realidad quiere decir 'conforme con ECMA 262 3'rd ed' ¿no? :)

Los métodos que usted se refiere son parte de la nueva edición 5 'th - para los navegadores que no soportan esta se puede utilizar la 'cuña' que se extiende siguiendo 3'rd en 5' th http://github.com/kriskowal/narwhal-lib/blob/narwhal-lib/lib/global-es5.js.

+1

eso es un buen comienzo, pero hay un buen número de errores en las implementaciones no tomadas de MDC. p.ej. muchos de los métodos de matriz no pasan suficientes argumentos a sus devoluciones de llamada, y no actúan del todo bien en el caso de una mutación de matriz en la función de devolución de llamada. – bobince

+0

Tomaré todo lo que pueda para hacer que js sea un lenguaje más sensato/mínimamente capaz. :-) – cemerick

27

Eche un vistazo a Underscore.js.

+2

ES5Shim y otros stubs (como MDC) tienden a tener otras consecuencias también. Lo mejor es utilizar guiones bajos u otra biblioteca para este tipo de funciones, que usarán los métodos internos donde estén disponibles. – Tracker1

+0

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

9

Kris Kowal ha compilado una pequeña biblioteca que actúa como una cuña para las funciones de ECMAScript 5 que pueden faltar en la implementación del navegador. Algunas de las funciones han sido revisadas en numerosas ocasiones por otras personas para optimizar su velocidad y solucionar los errores del navegador.Las funciones están escritas para seguir la especificación lo más cerca posible.

es5-shim.js se lanzó bajo la licencia de MIT, las extensiones Array.prototype están cerca de la parte superior y puede cortar y eliminar cualquier función que no necesite con bastante facilidad. También sugiero que minimices la secuencia de comandos ya que los comentarios la hacen mucho más grande de lo necesario.

1

Esos scripts no funcionan bien en mis pruebas. Creo un archivo con las mismas funciones basadas en MDN documentos.

demasiados problemas se resuelven las zonas en internet   Explorador   8. Consulte el código en egermano/ie-fix.js.

0

Con los Underscore.js

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

Cuestiones relacionadas