Perché indexOf non funziona su un array IE8?


294

La funzione seguente funziona perfettamente su Opera, Firefox e Chrome. Tuttavia, in IE8 fallisce da if ( allowed.indexOf(ext[1]) == -1)parte.

Qualcuno sa perché? C'è qualche errore evidente?

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

5
Ottima domanda, ottima risposta. Grazie per avermi dato esattamente quello di cui avevo bisogno.
Hardwareguy,

Risposte:


488

Le versioni di IE precedenti a IE9 non hanno una .indexOf()funzione per Array, per definire la versione esatta della specifica , esegui questa prima di provare a usarla:

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

Questa è la versione di MDN , utilizzata in Firefox / SpiderMonkey. In altri casi come IE, aggiungerà .indexOf()nel caso in cui manchi ... fondamentalmente IE8 o inferiore a questo punto.


2
Nota che se tu (o le librerie che usi) usi la sintassi for / in per enumerare le matrici (es. For (idx in arrayname) stmt;) che verrà enumerato anche questo metodo. Questo perché le proprietà incorporate non sono enumerate da for / in ma quelle definite dall'utente lo sono.
Treno Spagna,

5
@Mike - Questo è un problema diverso ... non dovresti usare un for...inciclo per iterare un array, dovrebbe essere usato solo per l' enumerazione .
Nick Craver

3
@Mike: per più motivi si scorre su un array..come ottenere i risultati nell'ordine giusto tra i browser. L'uso for..insu un array causerà solo problemi, non è solo una convenzione ... è un uso involontario e non corretto. L'ordine e le chiavi non sono entrambi completamente specificati, dipendono dall'implementazione ... ad esempio IE enumera gli elementi dell'array nell'ordine in cui sono stati aggiunti , non dal loro indice. Tuttavia puoi iterare correttamente, accedendo per indice.
Nick Craver

1
E ciò illustra la differenza tra l'enumerazione degli elementi e l'utilizzo di un indice per iterare. Ecco perché abbiamo entrambi i concetti. È possibile enumerare i valori in un elenco collegato oppure è possibile eseguire la ricerca per indicizzazione dell'elenco collegato e restituire i valori da uno all'altro. Uno è un concetto matematico, uno è un'istruzione procedurale.
jcolebrand,

1
@Pointy Sì! E poiché molti cercano "Perché IndexOf non funziona su un array IE8?" potrebbe essere a un livello di sofisticazione inferiore WRT a js, potrebbe essere utile indicarlo come corollario della risposta. Se tutti avessero già una conoscenza approfondita delle specifiche e delle differenze tra le implementazioni, thread come questi non esisterebbero. @Nick Fai forti ipotesi sulla correttezza. Esistono molte operazioni per le quali l'ordine non ha importanza (ad esempio, impostare la differenza). Inoltre, il commento originale non ha menzionato l'enumerazione nella sequenza dell'indice, solo che for / in include le definizioni utente.
Treno Spagna,

152

Se stai usando jQuery, puoi usare $ .inArray () invece.


7
Sono d'accordo che questo è più utile. Questo è uno dei motivi principali per l'utilizzo di JQuery: fa molto per alleviare le incompatibilità tra browser.
cw24

17

Se stai usando jQuery e vuoi continuare a utilizzare indexOf senza preoccuparti dei problemi di compatibilità, puoi farlo:

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

Questo è utile quando si desidera continuare a utilizzare indexOfma fornire un fallback quando non è disponibile.


Sì, probabilmente perché non ha incluso jQuery ¯_ (ツ) _ / ¯ È una sintassi valida.


5

Si prega di fare attenzione con $ .inArray se si desidera utilizzarlo. Ho appena scoperto che $ .inArray funziona solo con "Array", non con String. Ecco perché questa funzione non funzionerà in IE8!

L'API jQuery crea confusione

Il metodo $ .inArray () è simile al metodo .indexOf () nativo di JavaScript in quanto restituisce -1 quando non trova una corrispondenza. Se il primo elemento all'interno della matrice corrisponde a valore, $ .inArray () restituisce 0

-> Non dovrebbero dirlo "Simile". Dato che indexOf supporta anche "String"!


16
Si chiama inArray. Ciò sembra piuttosto definitivo da applicare solo agli array. Ecco perché è "simile a" e non "identico a".
tandrewnichols,

Buona nota Il fatto divertente è che indexOfun oggetto String si trova completamente in IE mentre indexOfin Array il prototipo non si trova in IE <= 8.
adi518

Lo stai legando al prototipo dell'array in modo che non influisca sulle stringhe.
Kagronick,

3

Il problema

IE <= 8 semplicemente non ha un indexOf()metodo per le matrici.


La soluzione

Se è necessario indexOfin IE <= 8, è necessario considerare l'utilizzo del seguente polyfill , raccomandato all'MDN :

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

Minimizzato:

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

1

Puoi usarlo per sostituire la funzione se non esiste:

<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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.