Warum funktioniert indexOf auf einem Array IE8 nicht?

294

Die folgende Funktion funktioniert problemlos in Opera, Firefox und Chrome. In IE8 schlägt dies jedoch teilweise fehl if ( allowed.indexOf(ext[1]) == -1).

Weiß jemand warum? Gibt es einen offensichtlichen Fehler?

function CheckMe() {
    var allowed = new Array('docx','xls','xlsx', 'mp3', 'mp4', '3gp', 'sis', 'sisx', 'mp3', 'wav', 'mid', 'amr', 'jpg', 'gif', 'png', 'jpeg', 'txt', 'pdf', 'doc', 'rtf', 'thm', 'rar', 'zip', 'htm', 'html', 'css', 'swf', 'jar', 'nth', 'aac', 'cab', 'wgz');
    var fileinput=document.getElementById('f');
    var ext = fileinput.value.toLowerCase().split('.');
    if ( allowed.indexOf(ext[1]) == -1) 
    {
        document.getElementById('uploadsec').innerHTML = document.getElementById('uploadsec').innerHTML;
        alert('This file type is not allowed!');
    }
}
nLL
quelle
5
Tolle Frage, tolle Antwort. Danke, dass du mir genau das gegeben hast, was ich brauchte.
Hardwareguy

Antworten:

488

Versionen von IE vor IE9 haben keine .indexOf()Funktion für Array. Um die genaue Spezifikationsversion zu definieren , führen Sie diese aus, bevor Sie versuchen, sie zu verwenden:

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

Dies ist die Version von MDN , die in Firefox / SpiderMonkey verwendet wird. In anderen Fällen wie dem IE wird es hinzugefügt, .indexOf()falls es fehlt ... im Grunde IE8 oder darunter an dieser Stelle.

Nick Craver
quelle
2
Beachten Sie die Einschränkung, dass, wenn Sie (oder Bibliotheken, die Sie verwenden) die for / in-Syntax verwenden, um Arrays aufzulisten (z. B. für (idx in arrayname) stmt;), diese Methode ebenfalls aufgelistet wird. Dies liegt daran, dass integrierte Eigenschaften nicht durch for / in aufgelistet werden, sondern durch benutzerdefinierte.
Spanien Zug
5
@Mike - Das ist ein anderes Problem ... Sie sollten keine for...inSchleife verwenden, um ein Array zu iterieren , es sollte nur für die Aufzählung verwendet werden .
Nick Craver
3
@Mike - Sie iterieren aus weiteren Gründen über ein Array. So erhalten Sie Ihre Ergebnisse in allen Browsern in der richtigen Reihenfolge. Die Verwendung for..inin einem Array verursacht nur Probleme, es ist nicht nur eine Konvention. Es ist eine unbeabsichtigte und eine falsche Verwendung. Die Reihenfolge und die Schlüssel sind beide nicht vollständig angegeben, sie sind implementierungsabhängig. Beispielsweise listet der IE die Array-Elemente in der Reihenfolge auf, in der sie hinzugefügt wurden , und nicht anhand ihres Index. Sie können jedoch korrekt iterieren und über den Index zugreifen.
Nick Craver
1
Dies zeigt den Unterschied zwischen der Aufzählung der Elemente und der Verwendung eines Index zum Iterieren. Deshalb haben wir beide Konzepte. Sie können die Werte in einer verknüpften Liste auflisten oder die verknüpfte Liste crawlen und die Werte von einer zur nächsten zurückgeben. Eines ist ein mathematisches Konzept, eines ist eine prozedurale Anweisung.
Jcolebrand
1
@Pointy Ja! Und da viele nach "Warum funktioniert indexOf auf einem Array IE8 nicht?" Suchen Es kann hilfreich sein, dies als eine Folge der Antwort herauszustellen. Wenn jeder bereits ein tiefes Verständnis für die Spezifikation und die Unterschiede zwischen den Implementierungen hätte, würden solche Threads nicht existieren. @Nick Sie machen starke Annahmen über die Richtigkeit. Es gibt viele Operationen, für die die Reihenfolge keine Rolle spielt (z. B. Differenz festlegen). Außerdem wurde im ursprünglichen Kommentar die Aufzählung in der Indexsequenz nicht erwähnt, nur dass für / in Benutzerdefinitionen enthalten sind.
Spanien Zug
152

Wenn Sie jQuery verwenden, können Sie stattdessen $ .inArray () verwenden.

tiegz
quelle
7
Ich bin damit einverstanden, dass dies nützlicher ist. Dies ist einer der Hauptgründe für die Verwendung von JQuery - es trägt wesentlich dazu bei, browserübergreifende Inkompatibilitäten zu verringern.
CW24
17

Wenn Sie jQuery verwenden und indexOf weiterhin verwenden möchten, ohne sich um Kompatibilitätsprobleme sorgen zu müssen, können Sie Folgendes tun:

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(val) {
        return jQuery.inArray(val, this);
    };
}

Dies ist hilfreich, wenn Sie weiterhin verwenden möchten, indexOfaber einen Fallback bereitstellen möchten, wenn dieser nicht verfügbar ist.

Mehdiway
quelle
Ja, wahrscheinlich, weil er jQuery ¯_ (ツ) _ / ¯ nicht eingeschlossen hat. Es ist eine gültige Syntax.
5

Bitte seien Sie vorsichtig mit $ .inArray, wenn Sie es verwenden möchten. Ich habe gerade herausgefunden, dass $ .inArray nur mit "Array" funktioniert, nicht mit String. Deshalb funktioniert diese Funktion in IE8 nicht!

Die jQuery-API sorgt für Verwirrung

Die $ .inArray () -Methode ähnelt der nativen .indexOf () -Methode von JavaScript, da sie -1 zurückgibt, wenn keine Übereinstimmung gefunden wird. Wenn das erste Element im Array mit dem Wert übereinstimmt, gibt $ .inArray () 0 zurück

-> Sie sollten es nicht "ähnlich" sagen. Da indexOf auch "String" unterstützt!

ptgamr
quelle
16
Es heißt inArray. Das scheint ziemlich definitiv nur für Arrays zu gelten. Deshalb ist es "ähnlich" und nicht "identisch mit".
Tandrewnichols
Gute Notiz. Die lustige Tatsache ist, dass indexOfein String-Objekt vollständig im IE gefunden wird, während der indexOfArray-Prototyp nicht im IE <= 8 gefunden wird.
adi518
Sie binden es an den Array-Prototyp, damit es keine Auswirkungen auf Zeichenfolgen hat.
Kagronick
3

Das Problem

IE <= 8 hat einfach keine indexOf()Methode für Arrays.


Die Lösung

Wenn Sie indexOfin IE <= 8 benötigen , sollten Sie die folgende Polyfüllung in Betracht ziehen , die im MDN empfohlen wird :

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(searchElement, fromIndex) {
        var k;
        if (this == null) {
            throw new TypeError('"this" is null or not defined');
        }
        var o = Object(this);
        var len = o.length >>> 0;
        if (len === 0) {
            return -1;
        }
        var n = +fromIndex || 0;
        if (Math.abs(n) === Infinity) {
            n = 0;
        }
        if (n >= len) {
            return -1;
        }
        k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
        while (k < len) {
            if (k in o && o[k] === searchElement) {
                return k;
            }
            k++;
        }
        return -1;
    };
}

Minimiert:

Array.prototype.indexOf||(Array.prototype.indexOf=function(r,t){var n;if(null==this)throw new TypeError('"this" is null or not defined');var e=Object(this),i=e.length>>>0;if(0===i)return-1;var a=+t||0;if(Math.abs(a)===1/0&&(a=0),a>=i)return-1;for(n=Math.max(a>=0?a:i-Math.abs(a),0);i>n;){if(n in e&&e[n]===r)return n;n++}return-1});
John Slegers
quelle
1

Sie können dies verwenden, um die Funktion zu ersetzen, wenn sie nicht vorhanden ist:

<script>
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;
    };
}
</script>
Robert Cadmire
quelle