Naprawianie funkcji JavaScript Array w przeglądarce Internet Explorer (indexOf, forEach itp.) [Zamknięte]

137

Jak szczegółowo gdzie indziej , a inaczej pozornie dobrze znane, Internet Explorer (wersja 7 zdecydowanie, aw niektórych przypadkach, wersja 8) nie realizują kluczowe funkcje, w szczególności na Array(takich jak forEach, indexOfitp).

Tu i ówdzie istnieje wiele obejść, ale wolałbym umieścić w naszej witrynie odpowiedni, kanoniczny zestaw implementacji, zamiast kopiować i wklejać lub hakować nasze własne implementacje. Znalazłem metody js , które wyglądają obiecująco, ale pomyślałem, że opublikuję tutaj, aby sprawdzić, czy inna biblioteka jest bardziej polecana. Kilka różnych kryteriów:

  • Biblioteka powinna po prostu nie działać dla tych funkcji, dla których przeglądarka ma już implementacje ( js-methodswydaje się, że tutaj całkiem nieźle).
  • Nie- GPL , proszę, chociaż LGPL jest akceptowalne.
cemerick
źródło

Odpowiedzi:

220

Wiele z nich korzysta z implementacji rezerwowych MDC (np. Dla indexOf ). Generalnie są rygorystycznie zgodne ze standardami, nawet w zakresie jawnego sprawdzania typów wszystkich argumentów.

Niestety, chociaż jest jasne, że autorzy uważają ten kod za trywialny i swobodnie używany, nie wydaje się, aby istniała wyraźna licencja na umieszczenie tego na piśmie. Wiki jako całość to CC Attribution-ShareAlike, jeśli jest to akceptowalna licencja (chociaż CC nie jest zaprojektowane dla kodu jako takiego).

js-Methods wygląda ogólnie OK, ale nie jest tak zgodne ze standardami na obrzeżach tego, jakie powinny być funkcje (np. niezdefiniowane elementy listy, funkcje, które mutują listę). Jest również pełen innych losowych, niestandardowych metod, w tym niektórych wątpliwych, takich jak podejrzane stripTags i niekompletny kodek UTF-8 (co jest również trochę niepotrzebne, biorąc pod uwagęunescape(encodeURIComponent) sztuczkę).

Co jest warte, oto czego używam (które niniejszym udostępniam jako własność publiczną, jeśli w ogóle można powiedzieć, że podlega prawom autorskim). Jest nieco krótszy niż wersje MDC, ponieważ nie próbuje wykryć typu, że nie zrobiłeś czegoś głupiego, takiego jak przekazywanie wywołań zwrotnych niefunkcyjnych lub indeksów innych niż całkowite, ale poza tym stara się być zgodny ze standardami. (Daj mi znać, jeśli coś przegapiłem. ;-))

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

Inne metody ECMA262-5, które nie zostały tutaj zaimplementowane, to Array reduce/ reduceRight, metody JSON i kilka nowych Objectmetod, które można niezawodnie zaimplementować jako funkcje JS.

bobince
źródło
5
Dzięki za ten wskaźnik - inne linki, które widziałem w mozdev, gdzie można było znaleźć takie impls, były nieaktualne. FYI, kod jest licencjonowany przez MIT, jak określono tutaj: developer.mozilla.org/Project:Copyrights (prawie tak dobry, jak możesz! :-)
cemerick
1
Co ciekawe, jeśli odwołuję się do pliku js zawierającego wszystkie implikacje MDC ECMA262-5 przed jquery 1.4.2, jquery jest zepsute - np. Wszystkie selektory zawodzą, zwracając wartość null. Przeniesienie implikacji MDC po jquery prowadzi do oczekiwanego zachowania. Bardzo dziwne.
cemerick
Że jest ciekawy! Przyjrzę się temu (masz przypadek testowy?) ... Nie mogę od razu pomyśleć, dlaczego tak się stało, chociaż to, co robi jQuery w linii 72, wygląda podejrzanie.
bobince
4
UWAGA: w większości przeglądarek, w których te kody pośredniczące są potrzebne, jeśli wykonasz polecenie „for (index in somearray) {...}”, będziesz musiał użyć somearray.hasOwnProperty (index) jako sprawdzenia. Silnik JS w IE <= 8 będzie zawierał rozszerzenia array.prototype. Kod asynchroniczny Google Adwords tego nie robi. Najlepiej użyć podkreślenia lub innej funkcji biblioteki, która ujednolica w tym zakresie.
Tracker 1
1
Jest to najszybsza implementacja indexOf () dla IE 8, jaką udało mi się znaleźć. Dzięki!
Alex Denysenko
27

Spójrz na Underscore.js .

rfunduk
źródło
2
ES5Shim i inne kody pośredniczące (takie jak z MDC) mają również inne konsekwencje. W przypadku tego typu funkcji najlepiej jest używać podkreślenia lub innej biblioteki, która użyje metod wewnętrznych, jeśli są dostępne.
Tracker 1
Z Underscore.js var arr = ['a', 'a1', 'b'] _.filter (arr, function (a) {return a.indexOf ('a')> -1;})
sri_bb
9

Kris Kowal skompilował małą bibliotekę, która działa jako podkładka dla funkcji ECMAScript 5, których może brakować w implementacji przeglądarki. Niektóre funkcje były wielokrotnie poprawiane przez inne osoby, aby zoptymalizować je pod kątem szybkości i obejść błędy przeglądarki. Funkcje zostały napisane tak, aby jak najbardziej odpowiadały specyfikacji.

es5-shim.js został wydany na licencji MIT, rozszerzenia Array.prototype znajdują się na szczycie i możesz łatwo wycinać i usuwać funkcje, których nie potrzebujesz. Proponuję również zminimalizować skrypt, ponieważ komentarze sprawiają, że jest on znacznie większy niż powinien.

Andy E.
źródło
1

Przez „nie wdrażaj kluczowych funkcji” masz na myśli „zgodne z ECMA 262 3. wydanie”, prawda? :)

Metody, do których się odnosisz, są częścią nowej piątej edycji - w przypadku przeglądarek, które jej nie obsługują, możesz użyć następującej `` podkładki '', która rozszerza 3. do 5. http://github.com/kriskowal/narwhal- lib / blob / narwhal-lib / lib / global-es5.js .

Sean Kinsey
źródło
1
To dobry początek, ale jest sporo błędów w implementacjach, które nie pochodzą z MDC. na przykład. wiele metod tablicowych nie przekazuje wystarczającej liczby argumentów do swoich wywołań zwrotnych i nie działa całkiem poprawnie w przypadku mutacji tablicy w funkcji wywołania zwrotnego.
bobince
Zrobię wszystko, co mogę, aby uczynić js bardziej rozsądnym / minimalnie zdolnym językiem. </snark> :-)
cemerick
1

Te skrypty nie działają dobrze w moich testach. Tworzę plik o tych samych funkcjach na podstawie dokumentów MDN .

W przeglądarce Internet Explorer 8 rozwiązano zbyt wiele problemów. Zobacz kod w egermano / ie-fix.js .

egermano
źródło
0

Dzięki plikowi Underscore.js

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

sri_bb
źródło