Beheben von JavaScript-Array-Funktionen in Internet Explorer (indexOf, forEach usw.) [geschlossen]

137

Wie detailliert an anderer Stelle , und auch sonst offenbar gut bekannt ist , Internet Explorer ( auf jeden Fall 7 - Version, und in einigen Fällen, Version 8) nicht implementieren Schlüsselfunktionen, insbesondere auf Array(wie forEach, indexOfusw.).

Hier und da gibt es eine Reihe von Problemumgehungen, aber ich möchte einen richtigen, kanonischen Satz von Implementierungen in unsere Site einbinden, anstatt unsere eigenen Implementierungen zu kopieren und einzufügen oder wegzuhacken. Ich habe js-Methoden gefunden , was vielversprechend aussieht, dachte aber, ich würde hier posten, um zu sehen, ob eine andere Bibliothek mehr empfohlen wird. Einige verschiedene Kriterien:

  • Die Bibliothek sollte nur ein No-Operation für die Funktionen sein, für die ein Browser bereits Implementierungen hat ( js-methodsscheint hier recht gut zu funktionieren).
  • Bitte keine GPL , obwohl LGPL akzeptabel ist.
Cemerick
quelle

Antworten:

220

Viele verwenden die MDC-Fallback-Implementierungen (z. B. für indexOf ). Sie sind im Allgemeinen streng standardkonform, selbst wenn die Typen aller Argumente explizit überprüft werden.

Obwohl es klar ist, dass die Autoren diesen Code als trivial und frei verwendbar betrachten, scheint es leider keine explizite Lizenzgewährung zu geben, um dies schriftlich niederzulegen. Das gesamte Wiki ist CC Attribution-ShareAlike, wenn dies eine akzeptable Lizenz ist (obwohl CC nicht für Code als solchen ausgelegt ist).

js-Methoden sehen im Allgemeinen in Ordnung aus, sind jedoch an den Rändern der Funktionen nicht so standardkonform (z. B. undefinierte Listenelemente, Funktionen, die die Liste mutieren). Es ist auch voll von anderen zufälligen nicht standardmäßigen Methoden, einschließlich einiger fragwürdiger Methoden wie den zwielichtigen stripTags und dem unvollständigen UTF-8-Codec (was angesichts des unescape(encodeURIComponent)Tricks ebenfalls etwas unnötig ist ).

Für das, was es wert ist, verwende ich Folgendes (das ich hiermit öffentlich zugänglich mache, wenn man sagen kann, dass es überhaupt urheberrechtlich geschützt ist). Es ist etwas kürzer als die MDC-Versionen, da es nicht versucht, zu tippen, dass Sie nicht etwas Dummes getan haben, wie nicht funktionale Rückrufe oder nicht ganzzahlige Indizes zu übergeben, aber abgesehen davon versucht es, standardkonform zu sein. (Lass es mich wissen, wenn ich etwas verpasst habe. ;-))

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

Andere ECMA262-5-Methoden, die hier nicht implementiert sind, umfassen Array reduce/ reduceRight, die JSON- ObjectMethoden und die wenigen neuen Methoden, die zuverlässig als JS-Funktionen implementiert werden können.

Bobince
quelle
5
Vielen Dank für diesen Hinweis - die anderen Links, die ich in Mozdev gesehen habe, wo solche Geräte gefunden werden könnten, waren veraltet. Zu
Ihrer Information
1
Interessanterweise ist jquery fehlerhaft, wenn ich vor jquery 1.4.2 auf eine js-Datei verweise, die alle MDC ECMA262-5-Impls enthält, z. B. wenn alle Selektoren fehlschlagen und null zurückgeben. Das Verschieben der MDC-Impls nach der Abfrage führt zu einem erwarteten Verhalten. Sehr komisch.
Cemerick
Das ist neugierig! Ich werde mir das ansehen (haben Sie einen Testfall?) ... Ich kann mir nicht sofort vorstellen, warum dies passieren könnte, obwohl das, was jQuery in Zeile 72 tut, verdächtig aussieht.
Bobince
4
HINWEIS: Wenn Sie in den meisten Browsern, in denen diese Stubs benötigt werden, ein "for (index in somearray) {...}" ausführen, müssen Sie somearray.hasOwnProperty (index) als Prüfung verwenden. Die JS-Engine von IE <= 8 enthält die Erweiterungen array.prototype. Der asynchrone Code von Google Adwords tut dies nicht. Verwenden Sie am besten den Unterstrich oder die Funktionalität einer anderen Bibliothek, die dies standardisiert.
Tracker1
1
Dies ist die schnellste indexOf () -Implementierung für IE 8, die ich finden konnte. Vielen Dank!
Alex Denysenko
27

Schauen Sie sich Underscore.js an .

rfunduk
quelle
2
ES5Shim und andere Stubs (wie von MDC) haben tendenziell auch andere Konsequenzen. Verwenden Sie für diese Art von Funktionen am besten einen Unterstrich oder eine andere Bibliothek, die die internen Methoden verwendet, sofern verfügbar.
Tracker1
Mit dem Underscore.js var arr = ['a', 'a1', 'b'] _.filter (arr, Funktion (a) {return a.indexOf ('a')> -1;})
sri_bb
9

Kris Kowal hat eine kleine Bibliothek zusammengestellt, die als Shim für ECMAScript 5-Funktionen dient, die möglicherweise in der Implementierung des Browsers fehlen. Einige der Funktionen wurden mehrfach von anderen Personen überarbeitet, um sie auf Geschwindigkeit zu optimieren und Browserfehler zu umgehen. Die Funktionen sind so geschrieben, dass sie der Spezifikation so genau wie möglich folgen.

es5-shim.js wurde unter der MIT-Lizenz veröffentlicht. Die Array.prototype-Erweiterungen befinden sich ganz oben und Sie können alle Funktionen, die Sie nicht benötigen, ganz einfach zerhacken und entfernen. Ich schlage auch vor, dass Sie das Skript minimieren, da die Kommentare es viel größer machen, als es sein muss.

Andy E.
quelle
1

Mit "Schlüsselfunktionen nicht implementieren" meinen Sie tatsächlich "entspricht der ECMA 262 3. Ausgabe", oder? :) :)

Die Methoden, auf die Sie sich beziehen, sind Teil der neuen 5. Ausgabe. Für Browser, die dies nicht unterstützen, können Sie das folgende "Shim" verwenden, das sich vom 3. bis zum 5. http://github.com/kriskowal/narwhal- erstreckt. lib / blob / narwhal-lib / lib / global-es5.js .

Sean Kinsey
quelle
1
Das ist ein guter Anfang, aber es gibt einige Fehler in den Implementierungen, die nicht aus MDC stammen. z.B. Viele der Array-Methoden übergeben ihren Rückrufen nicht genügend Argumente und verhalten sich bei einer Array-Mutation in der Rückruffunktion nicht ganz richtig.
Bobince
Ich werde alles nehmen, um js zu einer vernünftigeren / minimal fähigeren Sprache zu machen. </ snark> :-)
Cemerick
1

Diese Skripte funktionieren in meinen Tests nicht gut. Ich erstelle eine Datei mit den gleichen Funktionen basierend auf MDN- Dokumenten.

In Internet Explorer 8 werden zu viele Problembereiche gelöst. Siehe den Code in egermano / ie-fix.js .

Egermano
quelle
0

Mit der Underscore.js

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

sri_bb
quelle