2010-05-07 8 views
136

Come dettagliato elsewhere, e in altri termini apparentemente noto, Internet Explorer (sicuramente versione 7 e, in alcuni casi, versione 8) non implementa le funzioni chiave, in particolare su Array (come forEach, indexOf, ecc.).Correzione delle funzioni della matrice JavaScript in Internet Explorer (indexOf, forEach, ecc.)

Ci sono un certo numero di soluzioni alternative qua e là, ma mi piacerebbe piegare un insieme corretto, canonico di implementazioni nel nostro sito piuttosto che copiare e incollare o hackerare via le nostre implementazioni. Ho trovato js-methods, che sembra promettente, ma ho pensato di postare qui per vedere se un'altra libreria è più altamente raccomandata. Un paio di criteri vari:

  • La biblioteca dovrebbe essere solo un no-operazione per quelle funzioni che un browser ha già implementazioni per (js-methods sembra fare abbastanza bene qui).
  • Non GPL, per favore, anche se LGPL è accettabile.

risposta

218

Molti utilizzano le implementazioni di fallback MDC (ad esempio 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 come banale e liberamente utilizzabile, non sembra esserci un esplicito permesso di licenza per metterlo in forma scritta. Il wiki nel suo complesso è CC Attribution-ShareAlike, se è una licenza accettabile (sebbene CC non sia progettato per il codice in quanto tale).

js-methods ha un aspetto OK in generale, ma non è conforme agli standard rispetto a come dovrebbero essere le funzioni (ad esempio voci di elenco non definite, funzioni che mutano la lista). È anche pieno di altri metodi casuali non standard, compresi alcuni discutibili come il dubbo stripTags e il codec UTF-8 incompleto (che è anche un po 'inutile dato il trucco unescape(encodeURIComponent)).

Per quello che vale, ecco quello che uso (che con il presente rilascio di pubblico dominio, se si può dire che sia per tutto il copyright). È un po 'più breve rispetto alle versioni MDC in quanto non tenta di digitare sniff che non hai fatto qualcosa di sciocco come passare callback non funzionali o indici non interi, ma a parte questo tenta di essere conforme agli standard. (Fatemi sapere se ho 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 le poche nuove Object metodi che possono essere implementate in modo affidabile come funzioni JS.

+5

Grazie per quel puntatore - gli altri collegamenti che ho visto in mozdev in cui tali elementi potrebbero essere trovati erano obsoleti. Cordiali saluti, il codice è MIT-licenza, come specificato qui: https://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 MDC ECMA262-5 impls prima di jquery 1.4.2, jquery è rotto - es tutti i selettori falliscono, restituendo null. Lo spostamento delle imps MDC dopo jquery porta al comportamento previsto. Molto strano. – cemerick

+0

Questo * è * curioso! Vedrà che (hai un caso di test?) ... Non riesco a pensare immediatamente perché questo potrebbe accadere, anche se ciò che jQuery fa in linea 72 sembra sospetto. – bobince

1

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

I metodi a cui ti riferisci fanno parte della nuova edizione 5'th - per i browser che non supportano questo si può utilizzare il seguente 'spessore' che si estende 3'rd in 5'th http://github.com/kriskowal/narwhal-lib/blob/narwhal-lib/lib/global-es5.js.

+1

Questo è un buon inizio, ma ci sono alcuni errori nelle implementazioni non presi da MDC. per esempio. molti dei metodi dell'array non passano abbastanza argomenti ai loro callback e non agiscono correttamente nel caso di mutazione di array nella funzione di callback. – bobince

+0

Prenderò tutto ciò che posso fare per rendere js un linguaggio più sensato/minimamente capace. :-) – cemerick

27

Dai uno sguardo allo Underscore.js.

+2

ES5Shim e altri stub (come da MDC) tendono ad avere anche altre conseguenze. È preferibile utilizzare il carattere di sottolineatura o un'altra libreria per questi tipi di funzioni, che utilizzeranno i metodi interni laddove disponibili. – Tracker1

+0

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

9

Kris Kowal ha compilato una piccola libreria che funge da shim per le funzioni ECMAScript 5 che potrebbero mancare dall'implementazione del browser. Alcune delle 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 con la licenza MIT, le estensioni Array.prototype sono vicine alla parte superiore e puoi tagliare e rimuovere tutte le funzioni che non ti servono abbastanza facilmente. Suggerisco anche di minimizzare lo script in quanto i commenti lo rendono molto più grande di quanto dovrebbe essere.

1

Questi script non funzionano bene nei miei test. Creo un file con le stesse funzioni in base ai documenti MDN.

troppi problemi zone sono risolti in Internet Explorer     8. Vedere il codice in egermano/ie-fix.js.

0

Con le Underscore.js

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

Problemi correlati