Tại sao indexOf không hoạt động trên mảng IE8?


294

Chức năng dưới đây hoạt động tốt trên Opera, Firefox và Chrome. Tuy nhiên, trong IE8 nó không thành công if ( allowed.indexOf(ext[1]) == -1).

Có ai biết tại sao không? Có bất kỳ sai lầm rõ ràng?

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
Câu hỏi tuyệt vời, câu trả lời tuyệt vời. Cảm ơn đã cho tôi chính xác những gì tôi cần.
Phần cứng

Câu trả lời:


488

Các phiên bản IE trước IE9 không có .indexOf()chức năng cho Array, để xác định phiên bản thông số kỹ thuật chính xác , hãy chạy phiên bản này trước khi thử sử dụng nó:

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

Đây là phiên bản từ MDN , được sử dụng trong Firefox / SpiderMonkey. Trong các trường hợp khác như IE, nó sẽ thêm .indexOf()vào trong trường hợp nó bị thiếu ... về cơ bản là IE8 hoặc thấp hơn vào thời điểm này.


2
Lưu ý cảnh báo rằng nếu bạn (hoặc thư viện bạn sử dụng) sử dụng cú pháp for / in để liệt kê các mảng (ví dụ: (idx trong mảng tên) stmt;) thì phương thức này cũng sẽ được liệt kê. Điều này là do các thuộc tính tích hợp không được liệt kê bởi for / in nhưng thuộc tính do người dùng xác định là.
Tàu Tây Ban Nha

5
@Mike - Đó là một vấn đề khác ... bạn không nên sử dụng một for...invòng lặp để lặp lại một mảng, nó chỉ nên được sử dụng để liệt kê .
Nick Craver

3
@Mike - Bạn lặp đi lặp lại qua một mảng vì nhiều lý do cho điều đó..như nhận được kết quả của bạn theo đúng thứ tự trên các trình duyệt. Sử dụng for..intrên một mảng sẽ chỉ gây ra vấn đề, nó không chỉ là một quy ước .. đó là việc sử dụng ngoài ý muốn và không chính xác. Thứ tự và khóa đều không được chỉ định hoàn toàn, chúng phụ thuộc vào việc triển khai ... ví dụ IE sẽ liệt kê các mục mảng theo thứ tự chúng được thêm vào , không phải theo chỉ mục của chúng. Tuy nhiên, bạn có thể lặp lại chính xác, truy cập theo chỉ mục.
Nick Craver

1
Và điều đó minh họa sự khác biệt giữa việc liệt kê các yếu tố và sử dụng một chỉ mục để lặp lại. Đó là lý do tại sao chúng ta có cả hai khái niệm. Bạn có thể liệt kê các giá trị trong danh sách được liên kết hoặc bạn có thể thu thập dữ liệu danh sách được liên kết và trả lại các giá trị từ cái này sang cái khác. Một là một khái niệm toán học, một là một hướng dẫn thủ tục.
jcolebrand

1
@ Điểm có! Và vì nhiều người tìm kiếm "Tại sao indexOf không hoạt động trên mảng IE8?" có thể ở mức độ tinh vi thấp hơn WRT đối với js, có thể hữu ích khi chỉ ra điều này như một hệ quả tất yếu cho câu trả lời. Nếu mọi người đã có sự hiểu biết sâu sắc về thông số kỹ thuật và sự khác biệt giữa các lần triển khai, thì các luồng như thế này sẽ không tồn tại. @Nick Bạn đưa ra các giả định mạnh mẽ về tính đúng đắn. Có nhiều thao tác mà thứ tự không quan trọng (ví dụ: đặt chênh lệch.) Ngoài ra, nhận xét ban đầu không đề cập đến việc liệt kê trong chuỗi chỉ mục, chỉ có điều đó bao gồm / trong đó bao gồm người dùng def fn.
Tàu Tây Ban Nha

152

Nếu bạn đang sử dụng jQuery, bạn có thể sử dụng $ .inArray () .


7
Tôi đồng ý rằng điều này hữu ích hơn. Đó là một trong những lý do chính để sử dụng JQuery - nó giúp giảm bớt sự không tương thích của trình duyệt chéo.
cw24

17

Nếu bạn đang sử dụng jQuery và muốn tiếp tục sử dụng indexOf mà không phải lo lắng về các vấn đề tương thích, bạn có thể làm điều này:

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

Điều này hữu ích khi bạn muốn tiếp tục sử dụng indexOfnhưng cung cấp dự phòng khi không có sẵn.


Có, có lẽ vì anh ta không bao gồm jQuery _ () _ / ¯ Đó là cú pháp hợp lệ.


5

Hãy cẩn thận với $ .inArray nếu bạn muốn sử dụng nó. Tôi mới phát hiện ra rằng $ .inArray chỉ hoạt động với "Array", không phải với String. Đó là lý do tại sao chức năng này sẽ không hoạt động trong IE8!

API jQuery gây nhầm lẫn

Phương thức $ .inArray () tương tự như phương thức .indexOf () gốc của JavaScript ở chỗ nó trả về -1 khi không tìm thấy kết quả khớp. Nếu phần tử đầu tiên trong mảng khớp với giá trị, $ .inArray () trả về 0

-> Họ không nên nói nó "Tương tự". Vì indexOf cũng hỗ trợ "Chuỗi"!


16
Nó được gọi là inArray. Điều đó có vẻ khá dứt khoát chỉ áp dụng cho mảng. Đó là lý do tại sao nó "tương tự" và không "giống hệt".
tandrewnichols

Lưu ý tốt. Sự thật buồn cười là indexOftrong một đối tượng String được tìm thấy đầy đủ trong IE trong khi indexOfnguyên mẫu Array không được tìm thấy trong IE <= 8.
adi518

Bạn đang ràng buộc nó với nguyên mẫu mảng để nó không ảnh hưởng đến chuỗi.
kagronick

3

Vấn đề

IE <= 8 đơn giản là không có indexOf()phương thức cho mảng.


Giải pháp

Nếu bạn cần indexOftrong IE <= 8, bạn nên xem xét sử dụng polyfill sau , được khuyến nghị tại 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;
    };
}

Giảm thiểu:

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

Bạn có thể sử dụng điều này để thay thế chức năng nếu nó không tồn tại:

<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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.