Mengapa indexOf tidak berfungsi pada IE8 array?

294

Fungsi di bawah berfungsi dengan baik di Opera, Firefox dan Chrome. Namun, di IE8 gagal pada if ( allowed.indexOf(ext[1]) == -1)bagian tersebut.

Adakah yang tahu mengapa? Apakah ada kesalahan yang jelas?

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
sumber
5
Pertanyaan bagus, jawaban bagus. Terima kasih telah memberikan apa yang saya butuhkan.
Hardwareguy

Jawaban:

488

Versi IE sebelum IE9 tidak memiliki .indexOf()fungsi untuk Array, untuk menentukan versi spesifikasi yang tepat , jalankan ini sebelum mencoba menggunakannya:

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

Ini adalah versi dari MDN , digunakan di Firefox / SpiderMonkey. Dalam kasus lain seperti IE, itu akan menambah .indexOf()dalam kasus itu hilang ... pada dasarnya IE8 atau di bawah pada saat ini.

Nick Craver
sumber
2
Perhatikan peringatan bahwa jika Anda (atau perpustakaan yang Anda gunakan) menggunakan sintaks for / in untuk menghitung array (mis. Untuk (idx dalam arrayname) stmt;) bahwa metode ini juga akan dihitung. Ini karena properti bawaan tidak disebutkan oleh untuk / dalam tetapi yang ditentukan pengguna.
Kereta Spanyol
5
@ Mike - Itu masalah yang berbeda ... Anda seharusnya tidak menggunakan for...inloop untuk mengulangi array, itu harus digunakan untuk enumerasi saja.
Nick Craver
3
@ Mike - Anda beralih pada array untuk alasan yang lebih banyak untuk itu..seperti mendapatkan hasil Anda dalam urutan yang benar di seluruh browser. Menggunakan for..inpada array hanya akan menyebabkan masalah, itu bukan hanya sebuah konvensi .. itu penggunaan yang tidak disengaja dan salah. Urutan dan kunci keduanya tidak sepenuhnya ditentukan, mereka tergantung pada implementasi ... misalnya IE akan menghitung item array dalam urutan mereka ditambahkan , bukan oleh indeks mereka. Namun Anda dapat mengulangi dengan benar, mengakses dengan indeks.
Nick Craver
1
Dan itu menggambarkan perbedaan antara menghitung elemen dan menggunakan indeks untuk beralih. Itulah sebabnya kami memiliki kedua konsep tersebut. Anda dapat menghitung nilai dalam daftar tertaut, atau Anda dapat merayapi daftar tertaut dan mengembalikan nilai dari satu ke yang berikutnya. Satu adalah konsep matematika, satu adalah instruksi prosedural.
jcolebrand
1
@Pointy Ya! Dan karena banyak pencarian "Mengapa indexOf tidak bekerja pada array IE8?" mungkin pada tingkat kecanggihan yang lebih rendah WRT ke js, mungkin bermanfaat untuk menunjukkan ini sebagai akibat wajar dari jawabannya. Jika setiap orang sudah memiliki pemahaman yang mendalam tentang spesifikasi dan perbedaan antara implementasi, utas seperti ini tidak akan ada. @Nick Anda membuat asumsi kuat tentang kebenaran. Ada banyak operasi yang urutannya tidak masalah (mis., Atur perbedaan.) Juga, komentar asli tidak menyebutkan penghitungan dalam urutan indeks, hanya saja untuk / dalam termasuk pengguna def fn's.
Kereta Spanyol
152

Jika Anda menggunakan jQuery, Anda dapat menggunakan $ .inArray () sebagai gantinya.

tiegz
sumber
7
Saya setuju bahwa ini lebih bermanfaat. Itu adalah salah satu alasan utama untuk menggunakan JQuery - itu tidak banyak untuk mengurangi ketidakcocokan lintas browser.
cw24
17

Jika Anda menggunakan jQuery dan ingin tetap menggunakan indexOf tanpa khawatir tentang masalah kompatibilitas, Anda dapat melakukan ini:

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

Ini membantu ketika Anda ingin tetap menggunakan indexOftetapi memberikan fallback ketika itu tidak tersedia.

Mehdiway
sumber
Ya, mungkin karena dia tidak memasukkan jQuery ¯_ (ツ) _ / ¯ Ini adalah sintaks yang valid.
5

Harap berhati-hati dengan $ .inArray jika Anda ingin menggunakannya. Saya baru tahu bahwa $ .inArray hanya berfungsi dengan "Array", bukan dengan String. Itu sebabnya fungsi ini tidak akan berfungsi di IE8!

API jQuery membuat kebingungan

Metode $ .inArray () mirip dengan metode .indexOf () asli JavaScript yang mengembalikan -1 ketika tidak menemukan kecocokan. Jika elemen pertama dalam array cocok dengan nilai, $ .inArray () mengembalikan 0

-> Mereka seharusnya tidak mengatakannya "Mirip". Karena indexOf mendukung "String" juga!

ptgamr
sumber
16
Itu disebut inArray. Tampaknya cukup definitif untuk diterapkan pada array saja. Itu sebabnya "mirip dengan" dan bukan "identik dengan".
tandrewnichols
Catatan yang bagus. Fakta lucu adalah indexOfdalam objek String sepenuhnya ditemukan di IE sementara indexOfdi Array prototipe tidak ditemukan di IE <= 8.
adi518
Anda mengikatnya ke prototipe array sehingga tidak akan mempengaruhi string.
kagronick
3

Masalah

IE <= 8 tidak memiliki indexOf()metode untuk array.


Solusinya

Jika Anda membutuhkan indexOfdi IE <= 8, Anda harus mempertimbangkan menggunakan polyfill berikut , yang direkomendasikan di 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;
    };
}

Diperkecil:

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
sumber
1

Anda dapat menggunakan ini untuk mengganti fungsi jika tidak ada:

<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
sumber