So beheben Sie Array indexOf () in JavaScript für Internet Explorer-Browser

295

Wenn Sie längere Zeit mit JavaScript gearbeitet haben, wissen Sie, dass Internet Explorer die ECMAScript-Funktion für Array.prototype.indexOf () [einschließlich Internet Explorer 8] nicht implementiert. Dies ist kein großes Problem, da Sie die Funktionalität Ihrer Seite mit dem folgenden Code erweitern können.

Array.prototype.indexOf = function(obj, start) {
     for (var i = (start || 0), j = this.length; i < j; i++) {
         if (this[i] === obj) { return i; }
     }
     return -1;
}

Wann sollte ich das implementieren?

Sollte ich es auf allen meinen Seiten mit der folgenden Prüfung einschließen, die prüft, ob die Prototypfunktion vorhanden ist, und wenn nicht, den Array-Prototyp erweitern?

if (!Array.prototype.indexOf) {

    // Implement function here

}

Oder überprüfen Sie den Browser und implementieren Sie ihn einfach, wenn es sich um Internet Explorer handelt?

//Pseudo-code

if (browser == IE Style Browser) {

     // Implement function here

}
Bobby Borszich
quelle
Ist eigentlich Array.prototype.indexOfnicht Teil von ECMA-262 / ECMAScript. Siehe ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf Vielleicht denken Sie String.prototype.indexOf...
Crescent Fresh
5
Es ist eine Erweiterung, die nicht Teil des ursprünglichen Standards ist. Es sollte jedoch als Teil von Javascript 1.6 implementiert werden (was der IE nicht tut) developer.mozilla.org/en/New_in_JavaScript_1.6
Josh Stodola
1
@Josh: bezog sich nur auf "IE implementiert die ECMAScript-Funktion nicht ..."
Crescent Fresh
4
Ihre Implementierung von Array.indexOfberücksichtigt keine negativen Startindizes. Siehe Mozillas Vorschlag Stop-Gap-Implementierung hier: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
nickf
3
Ich habe die Frage auf "===" aktualisiert, weil ich mir Sorgen mache, dass die Leute sie mit "==" kopieren, und das wäre falsch - ansonsten ist es in Ordnung. Siehe Eli Greys Antwort.
Joshcomley

Antworten:

213

Mach es so...

if (!Array.prototype.indexOf) {

}

Wie von MDC empfohlen .

Im Allgemeinen ist der Browsererkennungscode ein großes Nein-Nein.

Josh Stodola
quelle
Ich habe nicht genügend Mitarbeiter, um die Frage zu bearbeiten, kann aber den ECMAScript-Jargon entfernen und durch den entsprechenden Wortlaut ersetzen. Nochmals
vielen
12
Seien Sie vorsichtig, wenn Sie diese Art der Erkennung verwenden. Eine andere Bibliothek implementiert diese Funktion möglicherweise, bevor Sie sie testen, und sie ist möglicherweise nicht standardkonform (der Prototyp hat dies vor einiger Zeit getan). Wenn ich in einer feindlichen Umgebung arbeiten würde (viele andere Programmierer, die viele verschiedene Bibliotheken verwenden), würde ich keinem dieser ...
Pablo Cabrera
Die Spalte "Verknüpft" ---> ist wirklich praktisch! Ich liebe die Antwort hier: stackoverflow.com/questions/1744310/…
Gordon
Muss es in jede js-Datei eingeschlossen werden?
rd22
Wer genau ist MDC?
Ferrybig
141

Alternativ können Sie die inArray-Funktion jQuery 1.2 verwenden , die für alle Browser geeignet ist :

jQuery.inArray( value, array [, fromIndex ] )
Moses Lee
quelle
Der 'indexOf' ist nativer Code (rechts). Wird die jQuery 'inArray ()' also so schnell sein, z. B. native verwenden, wenn verfügbar, und poly-fill, wenn nicht?
Jeach
10
Um meinen eigenen Kommentar (oben) zu beantworten, habe ich ihn gerade implementiert und in Chrome ist er so schnell wie bei Verwendung von 'indexOf ()', aber in IE 8 ist er sehr, sehr langsam ... zumindest wissen wir es dass 'inArray ()' native verwendet, wenn es kann.
Jeach
78

Der vollständige Code wäre dann:

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(obj, start) {
         for (var i = (start || 0), j = this.length; i < j; i++) {
             if (this[i] === obj) { return i; }
         }
         return -1;
    }
}

Eine wirklich gründliche Antwort und einen Code für diese und andere Array-Funktionen finden Sie unter Frage zum Stapelüberlauf. Beheben von JavaScript-Array-Funktionen in Internet Explorer (indexOf, forEach usw.) .

Luis Perez
quelle
2
Danke, dass du nur das Ganze hast. Ich besuche diese Seite häufig, wenn ich plattformübergreifend indexOf in einem neuen Projekt benötige, und Ihr Snippet ist das einzige mit vollständigem Code. :) Diese paar Sekunden summieren sich wirklich, wenn man diese Seite besucht.
dylnmc
16

Die Bibliothek underscore.js verfügt über eine indexOf- Funktion, die Sie stattdessen verwenden können:

_.indexOf([1, 2, 3], 2)
scotta7exander
quelle
4
Diese Antwort vermeidet das Durcheinander mit dem Array-Prototyp und delegiert an den nativen indexOf, sofern verfügbar. Ich mag das.
Brad Koch
Scheint der einfachste Weg zu sein, wenn Sie Unterstrich oder Lodash einfügen können
ChrisRich
10

Sie sollten überprüfen, ob es nicht mit definiert ist if (!Array.prototype.indexOf).

Auch Ihre Implementierung von indexOfist nicht korrekt. Sie müssen ===statt ==in Ihrer if (this[i] == obj)Anweisung verwenden, sonst [4,"5"].indexOf(5)wäre 1 entsprechend Ihrer Implementierung, was falsch ist.

Ich empfehle Ihnen, die Implementierung auf MDC zu verwenden .

Eli Gray
quelle
9

Es gibt eine offizielle Mozilla-Lösung: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

(function() {
    /**Array*/
    // Production steps of ECMA-262, Edition 5, 15.4.4.14
    // Reference: http://es5.github.io/#x15.4.4.14
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(searchElement, fromIndex) {
            var k;
            // 1. Let O be the result of calling ToObject passing
            //    the this value as the argument.
            if (null === this || undefined === this) {
                throw new TypeError('"this" is null or not defined');
            }
            var O = Object(this);
            // 2. Let lenValue be the result of calling the Get
            //    internal method of O with the argument "length".
            // 3. Let len be ToUint32(lenValue).
            var len = O.length >>> 0;
            // 4. If len is 0, return -1.
            if (len === 0) {
                return -1;
            }
            // 5. If argument fromIndex was passed let n be
            //    ToInteger(fromIndex); else let n be 0.
            var n = +fromIndex || 0;
            if (Math.abs(n) === Infinity) {
                n = 0;
            }
            // 6. If n >= len, return -1.
            if (n >= len) {
                return -1;
            }
            // 7. If n >= 0, then Let k be n.
            // 8. Else, n<0, Let k be len - abs(n).
            //    If k is less than 0, then let k be 0.
            k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
            // 9. Repeat, while k < len
            while (k < len) {
                // a. Let Pk be ToString(k).
                //   This is implicit for LHS operands of the in operator
                // b. Let kPresent be the result of calling the
                //    HasProperty internal method of O with argument Pk.
                //   This step can be combined with c
                // c. If kPresent is true, then
                //    i.  Let elementK be the result of calling the Get
                //        internal method of O with the argument ToString(k).
                //   ii.  Let same be the result of applying the
                //        Strict Equality Comparison Algorithm to
                //        searchElement and elementK.
                //  iii.  If same is true, return k.
                if (k in O && O[k] === searchElement) {
                    return k;
                }
                k++;
            }
            return -1;
        };
    }
})();
Will V King
quelle
1
Nur pedantisch zu sein, aber MDN ist nicht nur Mozilla. Es ist ein Community-Projekt, das Mozilla-Mitarbeiter, aber auch Freiwillige umfasst. Jeder kann mitmachen und Beiträge leisten.
ste2425
5

Ich würde dies jedem empfehlen, der nach fehlenden Funktionen sucht:

http://code.google.com/p/ddr-ecma5/

Es bringt die meisten der fehlenden ecma5-Funktionen in ältere Browser ein :)

Josh Mc
quelle
** Obwohl ich feststellen werde, dass ich in IE7 Probleme mit dieser Bibliothek hatte.
Josh Mc
2

Dies war meine Implementierung. Fügen Sie dies im Wesentlichen vor allen anderen Skripten auf der Seite hinzu. dh in Ihrem Master für eine globale Lösung für Internet Explorer 8. Ich habe auch die Trimmfunktion hinzugefügt, die in vielen Frameworks verwendet zu werden scheint.

<!--[if lte IE 8]>
<script>
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(obj, start) {
            for (var i = (start || 0), j = this.length; i < j; i++) {
                if (this[i] === obj) {
                    return i;
                }
            }
            return -1;
        };
    }

    if(typeof String.prototype.trim !== 'function') {
        String.prototype.trim = function() {
            return this.replace(/^\s+|\s+$/g, '');
        };
    };
</script>
<![endif]-->
Glennweb
quelle
2

Für mich geht das.

if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(elt /*, from*/) {
    var len = this.length >>> 0;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)? Math.ceil(from) : Math.floor(from);
    if (from < 0)
    from += len;

    for (; from < len; from++) {
      if (from in this && this[from] === elt)
        return from;
    }
    return -1;
  };
}
Allen Wong
quelle
1

Mit der Underscore.js

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

sri_bb
quelle