Sửa các hàm JavaScript Array trong Internet Explorer (indexOf, forEach, v.v.) [đã đóng]


137

Như đã trình bày ở những nơi khác , và nếu không rõ ràng nổi tiếng, trình duyệt Internet Explorer (chắc chắn phiên bản 7, và trong một số trường hợp, phiên bản 8) không thực hiện chức năng chủ chốt, đặc biệt là trên Array(ví dụ như forEach, indexOf, vv).

Có một số cách giải quyết ở đây và đó, nhưng tôi muốn xếp một bộ triển khai đúng đắn, hợp quy vào trang web của chúng tôi thay vì sao chép và dán hoặc hack đi trong các triển khai của chúng tôi. Tôi đã tìm thấy các phương pháp js , có vẻ đầy hứa hẹn, nhưng tôi nghĩ rằng tôi sẽ đăng lên đây để xem liệu một thư viện khác có được đề xuất cao hơn không. Một vài tiêu chí linh tinh:

  • Thư viện chỉ là không hoạt động đối với các chức năng mà trình duyệt đã triển khai ( js-methodsdường như hoạt động khá tốt ở đây).
  • Không GPL , xin vui lòng, mặc dù LGPL được chấp nhận.

Câu trả lời:


220

Nhiều người sử dụng các triển khai dự phòng MDC (ví dụ: cho indexOf ). Nhìn chung, chúng tuân thủ nghiêm ngặt các tiêu chuẩn, thậm chí đến mức kiểm tra rõ ràng các loại của tất cả các đối số.

Thật không may, trong khi rõ ràng rằng các tác giả coi mã này là tầm thường và có thể sử dụng tự do, dường như không có một giấy phép rõ ràng nào để đưa văn bản này vào văn bản. Toàn bộ wiki là CC Attribution-ShareAlike, nếu đó là giấy phép có thể chấp nhận (mặc dù CC không được thiết kế cho mã như vậy).

Các phương thức js nhìn chung có vẻ ổn, nhưng không tuân thủ các tiêu chuẩn xung quanh các cạnh của cách các chức năng được cho là (ví dụ: các mục danh sách không xác định, các hàm làm thay đổi danh sách). Nó cũng có đầy đủ các phương thức phi tiêu chuẩn ngẫu nhiên khác, bao gồm một số phương pháp nghi vấn như dải phân cách khéo léo và bộ giải mã UTF-8 không hoàn chỉnh (cũng không cần thiết một chút cho unescape(encodeURIComponent)thủ thuật này).

Đối với những gì nó có giá trị, đây là những gì tôi sử dụng (mà tôi sẽ phát hành vào phạm vi công cộng, nếu nó có thể được coi là có bản quyền). Nó ngắn hơn một chút so với các phiên bản MDC vì nó không cố gắng đánh hơi rằng bạn đã làm điều gì đó ngớ ngẩn như vượt qua các cuộc gọi lại không có chức năng hoặc các chỉ mục không nguyên, nhưng ngoài việc nó cố gắng tuân thủ các tiêu chuẩn. (Hãy cho tôi biết nếu tôi bỏ lỡ bất cứ điều gì.;))

'use strict';

// Add ECMA262-5 method binding if not supported natively
//
if (!('bind' in Function.prototype)) {
    Function.prototype.bind= function(owner) {
        var that= this;
        if (arguments.length<=1) {
            return function() {
                return that.apply(owner, arguments);
            };
        } else {
            var args= Array.prototype.slice.call(arguments, 1);
            return function() {
                return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
            };
        }
    };
}

// Add ECMA262-5 string trim if not supported natively
//
if (!('trim' in String.prototype)) {
    String.prototype.trim= function() {
        return this.replace(/^\s+/, '').replace(/\s+$/, '');
    };
}

// Add ECMA262-5 Array methods if not supported natively
//
if (!('indexOf' in Array.prototype)) {
    Array.prototype.indexOf= function(find, i /*opt*/) {
        if (i===undefined) i= 0;
        if (i<0) i+= this.length;
        if (i<0) i= 0;
        for (var n= this.length; i<n; i++)
            if (i in this && this[i]===find)
                return i;
        return -1;
    };
}
if (!('lastIndexOf' in Array.prototype)) {
    Array.prototype.lastIndexOf= function(find, i /*opt*/) {
        if (i===undefined) i= this.length-1;
        if (i<0) i+= this.length;
        if (i>this.length-1) i= this.length-1;
        for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */
            if (i in this && this[i]===find)
                return i;
        return -1;
    };
}
if (!('forEach' in Array.prototype)) {
    Array.prototype.forEach= function(action, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this)
                action.call(that, this[i], i, this);
    };
}
if (!('map' in Array.prototype)) {
    Array.prototype.map= function(mapper, that /*opt*/) {
        var other= new Array(this.length);
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this)
                other[i]= mapper.call(that, this[i], i, this);
        return other;
    };
}
if (!('filter' in Array.prototype)) {
    Array.prototype.filter= function(filter, that /*opt*/) {
        var other= [], v;
        for (var i=0, n= this.length; i<n; i++)
            if (i in this && filter.call(that, v= this[i], i, this))
                other.push(v);
        return other;
    };
}
if (!('every' in Array.prototype)) {
    Array.prototype.every= function(tester, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this && !tester.call(that, this[i], i, this))
                return false;
        return true;
    };
}
if (!('some' in Array.prototype)) {
    Array.prototype.some= function(tester, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this && tester.call(that, this[i], i, this))
                return true;
        return false;
    };
}

Các phương thức ECMA262-5 khác không được triển khai ở đây bao gồm Array reduce/ reduceRight, các phương thức JSON và một vài Objectphương thức mới có thể được triển khai một cách đáng tin cậy như các hàm JS.


5
Cảm ơn con trỏ đó - các liên kết khác mà tôi đã thấy trong mozdev nơi những hàm ý như vậy có thể được tìm thấy đã cũ. FYI, mã được MIT cấp phép, như được chỉ định ở đây: developer.mozilla.org/Project:Copyrights (về mức độ tốt nhất mà bạn có thể nhận được !:-)
cemerick

1
Thật thú vị, nếu tôi tham chiếu tệp js chứa tất cả MDC ECMA262-5 ngụ ý trước khi jquery 1.4.2, jquery bị hỏng - ví dụ: tất cả các bộ chọn đều thất bại, trả về null. Di chuyển MDC ngụ ý sau khi jquery dẫn đến hành vi dự kiến. Rất kỳ quặc.
cemerick

Đó tò mò! Sẽ xem xét điều đó (bạn có trường hợp thử nghiệm không?) ... Tôi không thể nghĩ ngay tại sao điều này có thể xảy ra, mặc dù những gì jQuery làm trên dòng 72 có vẻ đáng ngờ.
bobince

4
LƯU Ý: trong hầu hết các trình duyệt cần sử dụng các sơ khai này, nếu bạn thực hiện kiểm tra "for (index in somearray) {...}", bạn sẽ cần sử dụng somearray.hasOwnProperty (index) làm kiểm tra. Công cụ JS của IE <= 8 sẽ bao gồm các phần mở rộng Array.prototype trong phần này. Mã async Google Adwords không làm điều này. Tốt nhất để sử dụng Underscore hoặc chức năng của thư viện khác tiêu chuẩn hóa việc này.
Tracker1

1
Đây là cách triển khai indexOf () nhanh nhất cho IE 8 mà tôi có thể tìm thấy. Cảm ơn!
Alex Denysenko

27

Hãy xem Underscore.js .


2
ES5Shim và các cuống khác (như từ MDC) cũng có xu hướng có các hậu quả khác. Tốt nhất là sử dụng dấu gạch dưới hoặc thư viện khác cho các loại hàm này, chúng sẽ sử dụng các phương thức bên trong nếu có.
Tracker1

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

9

Kris Kowal đã biên soạn một thư viện nhỏ hoạt động như một bản tóm tắt cho các chức năng ECMAScript 5 có thể bị thiếu trong quá trình thực hiện của trình duyệt. Một số chức năng đã được người khác sửa đổi nhiều lần để được tối ưu hóa tốc độ và khắc phục các lỗi trình duyệt. Các chức năng được viết để tuân theo các đặc điểm kỹ thuật càng chặt chẽ càng tốt.

es5-shim.js được phát hành theo giấy phép MIT, các phần mở rộng Array.prototype nằm gần đầu và bạn có thể cắt và loại bỏ bất kỳ chức năng nào bạn không cần khá dễ dàng. Tôi cũng đề nghị bạn thu nhỏ kịch bản vì các bình luận làm cho nó lớn hơn nhiều so với mức cần thiết.


1

Bởi 'không thực hiện các chức năng chính' bạn thực sự có nghĩa là 'phù hợp với ECMA 262 3'rd ed' phải không? :)

Các phương pháp mà bạn đang đề cập là một phần của phiên bản 5'th mới - đối với các trình duyệt không hỗ trợ điều này, bạn có thể sử dụng 'shim' sau đây kéo dài từ 3 đến 5 http://github.com/kriskowal/narwhal- lib / blob / narwhal-lib / lib / global-es5.js .


1
Đó là một khởi đầu tốt, nhưng có khá nhiều lỗi trong việc triển khai không được lấy từ MDC. ví dụ. nhiều phương thức mảng không chuyển đủ đối số cho các cuộc gọi lại của chúng và không hành động hoàn toàn đúng trong trường hợp đột biến mảng trong hàm gọi lại.
bobince

Tôi sẽ lấy bất cứ điều gì tôi có thể làm để biến js thành một ngôn ngữ lành mạnh hơn / có khả năng tối thiểu. </ snark> :-)
cemerick

1

Những kịch bản đó không hoạt động tốt trong các thử nghiệm của tôi. Tôi tạo một tệp có cùng chức năng dựa trên các tài liệu MDN .

Quá nhiều vấn đề khu vực được giải quyết trong Internet Explorer 8. Xem mã trong egermano / eg-fix.js .


0

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.