Correzione delle funzioni dell'array JavaScript in Internet Explorer (indexOf, forEach, ecc.) [Chiuso]


137

Come dettagliato altrove , e in caso contrario a quanto pare ben noto, Internet Explorer (versione 7 definitivamente, e in alcuni casi, la versione 8) non implementano funzioni chiave, in particolare Array(come ad esempio forEach, indexOfe così via).

Ci sono un certo numero di soluzioni alternative qua e là, ma mi piacerebbe inserire nel nostro sito un set di implementazioni canonico adeguato anziché copiare e incollare o hackerare le nostre implementazioni. Ho trovato js-method , che sembra promettente, ma ho pensato di pubblicare qui per vedere se un'altra libreria è più altamente raccomandata. Un paio di criteri vari:

  • La libreria dovrebbe essere una semplice operazione per quelle funzioni per le quali un browser ha già implementazioni ( js-methodssembra funzionare abbastanza bene qui).
  • Non GPL , per favore, sebbene LGPL sia accettabile.

Risposte:


220

Molti utilizzano le implementazioni di fallback MDC (ad es. Per indexOf ). Sono generalmente rigorosamente conformi agli standard, anche nella misura in cui controllano esplicitamente i tipi di tutti gli argomenti.

Sfortunatamente, mentre è chiaro che gli autori considerano questo codice banale e liberamente utilizzabile, non sembra esserci una concessione esplicita della licenza per metterlo per iscritto. Il wiki nel suo insieme è CC Attribution-ShareAlike, se questa è una licenza accettabile (sebbene CC non sia progettato per il codice in quanto tale).

js-method sembra in generale OK, ma non è conforme agli standard ai margini di come dovrebbero essere le funzioni (es. voci di elenco non definite, funzioni che mutano l'elenco). È anche pieno di altri metodi non standard casuali, inclusi alcuni discutibili come il dodgy stripTags e il codec UTF-8 incompleto (che è anche un po 'inutile dato ilunescape(encodeURIComponent) trucco).

Per quello che vale, ecco quello che uso (che con la presente rilascio nel pubblico dominio, se si può dire che sia assolutamente protetto da copyright). È un po 'più breve rispetto alle versioni MDC in quanto non tenta di annusare il tipo che non hai fatto qualcosa di stupido come passare callback non funzionali o indici non interi, ma a parte questo cerca di essere conforme agli standard. (Fammi sapere se mi sono perso qualcosa. ;-))

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

Altri metodi ECMA262-5 non implementati qui includono Array reduce/ reduceRight, quelli JSON e i pochi nuovi Objectmetodi che possono essere implementati in modo affidabile come funzioni JS.


5
Grazie per quel puntatore - gli altri collegamenti che ho visto in mozdev dove si potevano trovare tali impls erano stantii. Cordiali saluti, il codice è concesso in licenza MIT, come specificato qui: developer.mozilla.org/Project:Copyrights (circa buono come si può ottenere! :-)
cemerick

1
È interessante notare che se faccio riferimento a un file js contenente tutti gli impls MDC ECMA262-5 prima di jquery 1.4.2, jquery viene interrotto, ad esempio tutti i selettori falliscono, restituendo null. Lo spostamento di MDC impls dopo jquery porta al comportamento previsto. Molto strano.
cemerick,

Questo è curioso! Lo guarderò (hai un caso di prova?) ... Non riesco immediatamente a pensare perché ciò possa accadere, anche se ciò che jQuery fa sulla linea 72 sembra sospetto.
bobince,

4
NOTA: nella maggior parte dei browser in cui sono necessari questi stub, se si fa "for (index in somearray) {...}" sarà necessario utilizzare somearray.hasOwnProperty (index) come controllo. Il motore JS di IE <= 8 includerà le estensioni array.prototype in questo. Il codice asincrono di Google Adwords non lo fa. Meglio usare Underscore, o funzionalità di un'altra libreria che si standardizza su questo.
Tracker 1

1
Questa è l'implementazione indexOf () più veloce per IE 8 che ho trovato. Grazie!
Alex Denysenko

27

Dai un'occhiata a Underscore.js .


2
ES5Shim e altri stub (come da MDC) tendono ad avere anche altre conseguenze. È meglio usare il trattino basso o un'altra libreria per questo tipo di funzioni, che utilizzerà i metodi interni ove disponibili.
Tracker 1

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

9

Kris Kowal ha compilato una piccola libreria che funge da shim per le funzioni di ECMAScript 5 che potrebbero mancare dall'implementazione del browser. Alcune funzioni sono state riviste numerose volte da altre persone per essere ottimizzate per la velocità e per aggirare i bug del browser. Le funzioni sono scritte per seguire le specifiche il più vicino possibile.

es5-shim.js è stato rilasciato sotto licenza MIT, le estensioni Array.prototype sono quasi in alto e puoi tagliare e rimuovere qualsiasi funzione che non ti serve abbastanza facilmente. Ti suggerisco anche di minimizzare lo script poiché i commenti lo rendono molto più grande di quanto debba essere.


1

Con "non implementare le funzioni chiave" si intende in realtà "conforme all'ECMA 262 3a edizione", giusto? :)

I metodi a cui ti riferisci fanno parte della nuova 5a edizione - per i browser che non lo supportano puoi utilizzare il seguente 'shim' che estende il 3o al 5o http://github.com/kriskowal/narwhal- lib / blob / narwhal-lib / lib / global-es5.js .


1
È un buon inizio, ma ci sono alcuni errori nelle implementazioni non prese da MDC. per esempio. molti dei metodi dell'array non trasmettono abbastanza argomenti ai loro callback e non agiscono in modo corretto in caso di mutazione dell'array nella funzione callback.
bobince,

Prenderò tutto il possibile per rendere js un linguaggio più sano / minimamente capace. </snark> :-)
cemerick,

1

Quegli script non funzionano bene nei miei test. Creo un file con le stesse funzioni basate su MDN documenti .

Troppe aree problematiche vengono risolte in Internet Explorer 8. Vedere il codice in egermano / ie-fix.js .


0

Con Underscore.js

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.