Cách sửa lỗi Array indexOf () trong JavaScript cho trình duyệt Internet Explorer


295

Nếu bạn đã làm việc với JavaScript ở bất kỳ độ dài nào, bạn biết rằng Internet Explorer không triển khai chức năng ECMAScript cho Array.prototype.indexOf () [bao gồm cả Internet Explorer 8]. Đây không phải là một vấn đề lớn, bởi vì bạn có thể mở rộng chức năng trên trang của mình bằng mã sau đây.

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

Khi nào tôi nên thực hiện điều này?

Tôi có nên bọc nó trên tất cả các trang của mình bằng kiểm tra sau, kiểm tra xem hàm nguyên mẫu có tồn tại không và nếu không, hãy tiếp tục và mở rộng nguyên mẫu Array?

if (!Array.prototype.indexOf) {

    // Implement function here

}

Hoặc kiểm tra trình duyệt và nếu đó là Internet Explorer thì chỉ cần thực hiện nó?

//Pseudo-code

if (browser == IE Style Browser) {

     // Implement function here

}

Trên thực tế Array.prototype.indexOfkhông phải là một phần của ECMA-262 / ECMAScript. Xem ecma-i Intl.org/publications/files/ECMA-ST/ECMA-262.pdf Có thể bạn đang nghĩ String.prototype.indexOf...
Lưỡi liềm tươi

5
Đây là một phần mở rộng, không phải là một phần của tiêu chuẩn ban đầu. Tuy nhiên, nó nên được triển khai như một phần của Javascript 1.6 (mà IE không thực hiện được) developer.mozilla.org/en/New_in_JavaScript_1.6
Josh Stodola

1
@Josh: chỉ đề cập đến "IE không triển khai chức năng ECMAScript ..."
Crescent Fresh

4
Việc thực hiện của Array.indexOfbạn không đưa các chỉ số bắt đầu tiêu cực vào tài khoản. Xem triển khai ngăn chặn đề xuất của Mozilla tại đây: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/
Kẻ

3
Tôi đã cập nhật câu hỏi để sử dụng "===", bởi vì tôi lo lắng mọi người sẽ sao chép nó với "==" và điều đó sẽ sai - ngoài điều đó thì tốt. Xem câu trả lời của Eli Grey.
joshcomley

Câu trả lời:


213

Làm như thế này ...

if (!Array.prototype.indexOf) {

}

Theo khuyến nghị của MDC .

Nói chung, mã phát hiện trình duyệt là một không lớn.


Tôi không có đủ đại diện để chỉnh sửa câu hỏi nhưng vui lòng xóa biệt ngữ ECMAScript và thay thế bằng từ ngữ thích hợp. Cảm ơn một lần nữa
Bobby Borszich

12
Hãy cẩn thận nếu bạn sử dụng loại phát hiện này. Một thư viện khác có thể thực hiện chức năng này trước khi bạn kiểm tra nó và nó có thể không tuân thủ tiêu chuẩn (nguyên mẫu đã thực hiện cách đây một thời gian). Nếu tôi đang làm việc trong một môi trường thù địch (rất nhiều lập trình viên khác sử dụng nhiều thư viện riêng biệt), tôi sẽ không tin bất kỳ ai trong số này ...
Pablo Cabrera

Cột "Liên kết" ---> thực sự tiện dụng! Tôi thích câu trả lời ở đây: stackoverflow.com/questions/1744
310/ từ

Nó có phải được bọc trong mọi tập tin js không?
16:04

MDC chính xác là ai?
Ferrybig

141

Ngoài ra, bạn có thể sử dụng hàm inArray jQuery 1.2 , hoạt động trên các trình duyệt:

jQuery.inArray( value, array [, fromIndex ] )

'IndexOf' là mã gốc (phải), do đó, 'inArray ()' của jQuery sẽ nhanh như vậy, chẳng hạn như sử dụng nguồn gốc khi có sẵn và poly-fill khi không?
Jeach

10
Ok để trả lời nhận xét của riêng tôi (ở trên), tôi chỉ triển khai nó và trên Chrome nhanh như khi tôi sử dụng 'indexOf ()', nhưng trong IE 8 thì rất, rất chậm ... vì vậy ít nhất chúng ta biết that 'inArray ()' sử dụng nguồn gốc khi có thể.
Jeach

78

Mã đầy đủ sau đó sẽ là:

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

Để có câu trả lời thực sự kỹ lưỡng và mã cho vấn đề này cũng như các hàm mảng khác, hãy kiểm tra câu hỏi Stack Overflow Sửa các hàm JavaScript Array trong Internet Explorer (indexOf, forEach, v.v.) .


2
cảm ơn bạn chỉ cần có đầy đủ Tôi truy cập trang này thường xuyên bất cứ khi nào tôi cần indexOf đa nền tảng trong một dự án mới và đoạn mã của bạn là trang duy nhất có đầy đủ mã. :) Vài giây đó thực sự cộng lại khi một người thường xuyên truy cập trang này.
dylnmc


10

Bạn nên kiểm tra nếu nó không được xác định bằng cách sử dụng if (!Array.prototype.indexOf).

Ngoài ra, việc thực hiện của bạn indexOflà không chính xác. Bạn phải sử dụng ===thay vì ==trong if (this[i] == obj)tuyên bố của mình , nếu không [4,"5"].indexOf(5)sẽ là 1 theo cách triển khai của bạn, điều này không chính xác.

Tôi khuyên bạn nên sử dụng triển khai trên MDC .


9

Có giải pháp chính thức của Mozilla: 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;
        };
    }
})();

1
Chỉ là mô phạm nhưng MDN không chỉ là Mozilla. Đây là một dự án hướng đến cộng đồng có chứa nhân viên Mozilla nhưng cũng có các tình nguyện viên, bất kỳ ai cũng có thể tham gia và đóng góp.
ste2425

5

Tôi muốn giới thiệu điều này cho bất cứ ai đang tìm kiếm chức năng bị thiếu:

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

Nó mang lại hầu hết các chức năng ecma5 còn thiếu cho các trình duyệt cũ hơn :)


** Mặc dù tôi sẽ lưu ý rằng tôi đã gặp vấn đề trong IE7 với lib này.
Josh Mc

2

Đây là thực hiện của tôi. Về cơ bản, thêm phần này trước bất kỳ tập lệnh nào khác trên trang. tức là trong chủ của bạn cho một giải pháp toàn cầu cho Internet Explorer 8. Tôi cũng đã thêm vào chức năng cắt mà dường như được sử dụng trong phân bổ các khung.

<!--[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]-->

2

nó làm việc cho tôi

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

1

Với Underscore.js

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

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.