การแก้ไขฟังก์ชั่น JavaScript Array ใน Internet Explorer (indexOf, forEach ฯลฯ ) [ปิด]


137

ตามรายละเอียดอื่น ๆและอื่น ๆ ที่เห็นได้ชัดที่รู้จักกันดี, Internet Explorer (แน่นอน 7 รุ่นและในบางกรณี, รุ่น 8) ไม่ใช้ฟังก์ชั่นที่สำคัญโดยเฉพาะอย่างยิ่งบนArray(เช่นforEach, indexOfฯลฯ )

มีวิธีแก้ไขปัญหาจำนวนมากที่นี่และที่นั่น แต่ฉันต้องการพับชุดการใช้งานที่เหมาะสมและเป็นที่ยอมรับลงในไซต์ของเราแทนที่จะคัดลอกและวางหรือแฮ็กในการใช้งานของเราเอง ฉันพบวิธีการ jsแล้วซึ่งดูเหมือนว่าจะมีแนวโน้ม แต่คิดว่าฉันจะโพสต์ที่นี่เพื่อดูว่ามีห้องสมุดอื่นที่ได้รับการแนะนำสูงกว่านี้หรือไม่ เกณฑ์สองสามประการ:

  • ไลบรารี่ควรจะไม่ทำงานสำหรับฟังก์ชั่นเหล่านั้นที่เบราว์เซอร์มีการใช้งานอยู่แล้ว ( js-methodsดูเหมือนจะทำได้ดีที่นี่)
  • ไม่ใช่GPLโปรดแม้ว่าLGPLจะเป็นที่ยอมรับ

คำตอบ:


220

หลายคนใช้การใช้งาน fallback MDC (เช่นสำหรับindexOf ) โดยทั่วไปแล้วจะเป็นไปตามมาตรฐานอย่างเข้มงวดแม้ในการตรวจสอบประเภทของข้อโต้แย้งทั้งหมดอย่างชัดเจน

น่าเสียดายที่ผู้เขียนเห็นว่ารหัสนี้เป็นเพียงเรื่องเล็กน้อยและสามารถใช้งานได้อย่างอิสระ แต่ดูเหมือนว่าจะไม่มีการอนุญาตให้ใช้สิทธิ์อย่างชัดเจนในการเขียนนี้ wiki โดยรวมคือ CC Attribution-ShareAlike ถ้าเป็นใบอนุญาตที่ยอมรับได้ (แม้ว่า CC จะไม่ได้รับการออกแบบมาสำหรับรหัสเช่นนั้น)

js-methods ดูตกลงโดยทั่วไป แต่ไม่เป็นไปตามมาตรฐานรอบขอบของวิธีการทำงานที่ควรจะเป็น (เช่นรายการที่ไม่ได้กำหนดรายการฟังก์ชั่นที่กลายพันธุ์รายการ) นอกจากนี้ยังเต็มไปด้วยวิธีการที่ไม่ได้มาตรฐานแบบสุ่มอื่น ๆ รวมถึงวิธีที่น่าสงสัยบางอย่างเช่น dodgy stripTags และตัวแปลงสัญญาณ UTF-8 ที่ไม่สมบูรณ์ (ซึ่งก็ไม่จำเป็นunescape(encodeURIComponent)ด้วย

สำหรับสิ่งที่คุ้มค่านี่คือสิ่งที่ฉันใช้ (ซึ่งฉันจะปล่อยสู่สาธารณสมบัติหากสามารถกล่าวได้ว่ามีลิขสิทธิ์) มันสั้นกว่ารุ่น MDC เล็กน้อยเนื่องจากไม่ได้พยายามพิมพ์ sniff ที่คุณไม่ได้ทำอะไรโง่ ๆ เช่น pass call ที่ไม่ใช่ฟังก์ชั่นหรือดัชนีที่ไม่ใช่จำนวนเต็ม แต่นอกเหนือจากนั้นก็พยายามที่จะเป็นไปตามมาตรฐาน (แจ้งให้เราทราบหากฉันไม่ได้รับอะไรเลย ;-))

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

วิธี ECMA262-5 อื่น ๆ ที่ไม่ได้นำมาใช้ในที่นี้รวมถึง Array reduce/ reduceRight, JSON และObjectวิธีการใหม่บางอย่างที่สามารถใช้งานได้อย่างน่าเชื่อถือในฐานะฟังก์ชัน JS


5
ขอบคุณสำหรับตัวชี้นั้น - ลิงก์อื่น ๆ ที่ฉันเคยเห็นใน mozdev ซึ่งอาจพบว่าความหมายนั้นค้างอยู่ FYI รหัสนี้ได้รับอนุญาตจาก MIT ตามที่ระบุไว้ที่นี่: developer.mozilla.org/Project:Copyrights (ประมาณดีเท่าที่คุณจะได้รับ! :-)
cemerick

1
ที่น่าสนใจถ้าฉันอ้างอิงไฟล์ js ที่มี MDC ECMA262-5 ทั้งหมดแสดงถึง jquery 1.4.2 jquery จะใช้งานไม่ได้เช่นตัวเลือกทั้งหมดล้มเหลวส่งคืน null การย้าย MDC หมายถึงหลังจาก jquery นำไปสู่พฤติกรรมที่คาดหวัง แปลกมาก.
cemerick

นั่นคืออยากรู้! จะดูที่ (คุณมีกรณีทดสอบ?) ... ฉันไม่สามารถคิดได้ทันทีว่าทำไมสิ่งนี้อาจเกิดขึ้นแม้ว่าสิ่งที่ jQuery ทำในบรรทัดที่ 72 ดูน่าสงสัย
bobince

4
หมายเหตุ: ในเบราว์เซอร์ส่วนใหญ่ที่ต้องการสตับเหล่านี้หากคุณทำ "for (index ใน somearray) {... }" คุณจะต้องใช้ somearray.hasOwnProperty (index) เป็นการตรวจสอบ เอ็นจิน JS ของ IE <= 8 จะรวมส่วนขยาย array.prototype ไว้ในนี้ด้วย รหัส async ของ Google Adwords ไม่ได้ทำเช่นนี้ ดีที่สุดที่จะใช้ขีดล่างหรือฟังก์ชั่นของห้องสมุดอื่นที่เป็นมาตรฐานในเรื่องนี้
Tracker1

1
นี่เป็นการใช้งาน indexOf () ที่เร็วที่สุดสำหรับ IE 8 ที่ฉันเจอ ขอบคุณ!
Alex Denysenko

27

ลองดูที่Underscore.js


2
ES5Shim และส่วนอื่น ๆ (เช่นจาก MDC) มีแนวโน้มที่จะมีผลกระทบอื่น ๆ เช่นกัน เป็นการดีที่สุดที่จะใช้ขีดล่างหรือไลบรารีอื่นสำหรับฟังก์ชันประเภทนี้ซึ่งจะใช้วิธีการภายในหากมี
Tracker1

ด้วย Underscore.js var arr = ['a', 'a1', 'b'] _.filter (arr, ฟังก์ชั่น (a) {return a.indexOf ('a')> -1;})
sri_bb

9

Kris Kowalได้รวบรวมไลบรารีขนาดเล็กที่ทำหน้าที่เป็น shim สำหรับฟังก์ชัน ECMAScript 5 ที่อาจหายไปจากการนำเบราว์เซอร์มาใช้ ฟังก์ชั่นบางอย่างได้รับการปรับปรุงหลายครั้งโดยคนอื่น ๆ เพื่อให้ได้ความเร็วที่เหมาะสมและแก้ไขข้อผิดพลาดของเบราว์เซอร์ ฟังก์ชั่นถูกเขียนขึ้นเพื่อทำตามข้อกำหนดที่ใกล้เคียงที่สุด

es5-shim.jsเผยแพร่ภายใต้ลิขสิทธิ์ของ MIT ส่วนขยาย Array.prototype อยู่ใกล้กับด้านบนและคุณสามารถสับและเอาฟังก์ชั่นใด ๆ ที่คุณไม่ต้องการได้อย่างง่ายดาย ฉันยังแนะนำให้คุณย่อขนาดสคริปต์เนื่องจากความคิดเห็นทำให้มีขนาดใหญ่เกินกว่าที่จำเป็น


1

โดย 'ไม่ใช้งานฟังก์ชั่นที่สำคัญ' คุณหมายถึง 'สอดคล้องกับ ECMA 262 3'rd ed' ใช่ไหม? :)

วิธีการที่คุณอ้างถึงเป็นส่วนหนึ่งของรุ่นที่ 5'th ใหม่ - สำหรับเบราว์เซอร์ที่ไม่สนับสนุนสิ่งนี้คุณสามารถใช้ 'shim' ต่อไปนี้ที่ขยาย 3'rd เป็น 5'th http://github.com/kriskowal/narwhal- lib


1
เป็นการเริ่มต้นที่ดี แต่มีข้อผิดพลาดเล็กน้อยในการใช้งานที่ไม่ได้มาจาก MDC เช่น. วิธีการอาเรย์จำนวนมากไม่ส่งผ่านอาร์กิวเมนต์ที่เพียงพอไปยังการเรียกกลับของพวกเขาและไม่ได้ทำค่อนข้างถูกต้องในกรณีของการกลายพันธุ์อาเรย์ในฟังก์ชั่นการโทรกลับ
bobince

ฉันจะทำทุกอย่างที่จะทำให้ js เป็นภาษาที่มีความสามารถ / มีความสามารถน้อยที่สุด </snark> :-)
cemerick

1

สคริปต์เหล่านั้นทำงานได้ไม่ดีในการทดสอบของฉัน ฉันสร้างไฟล์ที่มีฟังก์ชั่นเดียวกันกับเอกสารMDN

พื้นที่ปัญหามากเกินไปจะแก้ไขได้ใน Internet Explorer 8 ดูรหัสในegermano / เช่น-fix.js


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.