Arreglando funciones de matriz de JavaScript en Internet Explorer (indexOf, forEach, etc.) [cerrado]

137

Como se detalla en otra parte , y de otra manera aparentemente conocida, Internet Explorer (definitivamente la versión 7 y, en algunos casos, la versión 8) no implementa funciones clave, en particular en Array(comoforEach , indexOf, etc.).

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

  • La biblioteca no debería ser una operación para aquellas funciones para las que un navegador ya tiene implementaciones (js-methods parece que funciona bastante bien aquí).
  • No GPL , por favor, aunque LGPL es aceptable.
cemerick
fuente

Respuestas:

220

Muchos usan 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.

Desafortunadamente, aunque está claro 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 el código como tal).

js-method se ve bien en general, pero no cumple con los estándares en torno a los límites de cómo se supone que deben ser las funciones (por ejemplo, elementos de lista no definidos, funciones que mutan la lista). También está lleno de otros métodos aleatorios no estándar, incluidos algunos cuestionables como las etiquetas de tiras poco fiables y el códec UTF-8 incompleto (que también es un poco innecesario dado elunescape(encodeURIComponent) truco).

Para lo que vale, esto es lo que uso (que por la presente publico en el dominio público, si se puede decir que tiene derechos de autor). Es un poco más corto que las versiones de MDC, ya que no intenta detectar que no ha hecho algo tonto, como pasar devoluciones de llamada sin función o índices no enteros, pero aparte de eso, intenta cumplir con los estándares. (Avísame si me he perdido algo. ;-))

'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 implementados aquí incluyen Array reduce/ reduceRight, los JSON y los pocos Objectmétodos nuevos que pueden implementarse de manera confiable como funciones JS.

bobince
fuente
55
Gracias por ese puntero: los otros enlaces que he visto en mozdev donde se pueden encontrar tales implicaciones estaban obsoletos. Para su información, el código tiene licencia MIT, como se especifica aquí: developer.mozilla.org/Project:Copyrights (¡lo mejor que puede obtener! :-)
cemerick
1
Curiosamente, si hago referencia a un archivo js que contiene todas las implicaciones de MDC ECMA262-5 antes de jquery 1.4.2, jquery está roto, por ejemplo, todos los selectores fallan y devuelven nulo. Mover las implicaciones de MDC después de jquery conduce al comportamiento esperado. Muy raro.
cemerick
Eso es curioso! Veré eso (¿tiene 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
44
NOTA: en la mayoría de los navegadores donde se necesitan estos apéndices, si hace un "for (index in somearray) {...}" deberá usar somearray.hasOwnProperty (index) como comprobación. El motor JS de IE <= 8 incluirá las extensiones array.prototype en esto. El código asincrónico de Google Adwords no hace esto. Es mejor utilizar el subrayado, o la funcionalidad de otra biblioteca que se estandariza en esto.
Rastreador1
1
Esta es la implementación más rápida de indexOf () para IE 8 que pude encontrar. ¡Gracias!
Alex Denysenko
27

Echa un vistazo a Underscore.js .

rfunduk
fuente
2
ES5Shim y otros trozos (como de MDC) también tienden a tener otras consecuencias. Es mejor utilizar guiones bajos u otra biblioteca para este tipo de funciones, que utilizarán los métodos internos cuando estén disponibles.
Rastreador1
Con el Underscore.js var arr = ['a', 'a1', 'b'] _.filter (arr, function (a) {return a.indexOf ('a')> -1;})
sri_bb
9

Kris Kowal ha compilado una pequeña biblioteca que actúa como un calce 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 la velocidad y evitar 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 MIT, las extensiones del prototipo Array están cerca de la parte superior y puede cortar y eliminar cualquier función que no necesite con bastante facilidad. También le sugiero que minimice el script ya que los comentarios lo hacen mucho más grande de lo que debe ser.

Andy E
fuente
1

Por 'no implementar funciones clave' realmente quiere decir 'se ajusta al ECMA 262 3'rd ed' ¿verdad? :)

Los métodos a los que se refiere son parte de la nueva quinta edición: para los navegadores que no lo admiten, puede usar la siguiente 'cuña' que se extiende de la tercera a la quinta http://github.com/kriskowal/narwhal- lib / blob / narwhal-lib / lib / global-es5.js .

Sean Kinsey
fuente
1
Es un buen comienzo, pero hay bastantes errores en las implementaciones que no se han tomado 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 mutación de matriz en la función de devolución de llamada.
bobince
Tomaré todo lo que pueda para hacer que js sea un lenguaje más sano / con una capacidad mínima. </snark> :-)
cemerick
1

Esas secuencias de comandos no funcionan bien en mis pruebas. Creo un archivo con las mismas funciones basado en MDN documentos .

Se resuelven demasiadas áreas de problemas en Internet Explorer 8. Consulte el código en egermano / ie-fix.js .

egermano
fuente
0

Con el Underscore.js

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

sri_bb
fuente