เหตุใด indexOf จึงไม่ทำงานกับอาร์เรย์ IE8


294

ฟังก์ชั่นด้านล่างทำงานได้ดีบน Opera, Firefox และ Chrome อย่างไรก็ตามใน IE8 มันล้มเหลวในif ( allowed.indexOf(ext[1]) == -1)ส่วน

ไม่มีใครรู้ว่าทำไม มีข้อผิดพลาดที่ชัดเจนหรือไม่?

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
คำถามที่ดีคำตอบที่ดี ขอบคุณที่ให้สิ่งที่ฉันต้องการ
Hardwareguy

คำตอบ:


488

รุ่นของ IE ก่อน IE9 ไม่มี.indexOf()ฟังก์ชั่นสำหรับ Array เพื่อกำหนดเวอร์ชั่นจำเพาะที่แน่นอนให้รันสิ่งนี้ก่อนที่จะลองใช้:

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

นี่คือรุ่นจาก MDN ที่ใช้ใน Firefox / SpiderMonkey ในกรณีอื่น ๆ เช่น IE มันจะเพิ่ม.indexOf()ในกรณีที่มันหายไป ... โดยทั่วไปแล้ว IE8 หรือต่ำกว่าที่จุดนี้


2
หมายเหตุข้อสังเกตว่าถ้าคุณ (หรือไลบรารีที่คุณใช้) ใช้สำหรับ / ในไวยากรณ์เพื่อระบุอาร์เรย์ (เช่น (สำหรับ idx ใน arrayname) stmt;) ว่าวิธีนี้จะถูกระบุเช่นกัน นี่เป็นเพราะคุณสมบัติในตัวไม่ได้ระบุโดย for / in แต่คุณสมบัติที่ผู้ใช้กำหนดคือ
Spain Train

5
@ ไมค์ - นั่นเป็นปัญหาที่แตกต่างกัน ... คุณไม่ควรใช้การfor...inวนซ้ำเพื่อทำซ้ำอาร์เรย์คุณควรใช้สำหรับการแจงนับ เท่านั้น
Nick Craver

3
@Mike - คุณวนซ้ำแถวลำดับด้วยเหตุผลเพิ่มเติมเพื่อที่จะได้รับผลลัพธ์ที่ถูกต้องในเบราว์เซอร์ การใช้for..inอาเรย์จะทำให้เกิดปัญหาเท่านั้นไม่ใช่เพียงการประชุม .. มันเป็นการใช้งานที่ไม่ตั้งใจและไม่ถูกต้อง ทั้งสองคำสั่งซื้อและคีย์ไม่ได้ระบุไว้อย่างสมบูรณ์พวกเขากำลังดำเนินการขึ้นอยู่กับ ... ตัวอย่างเช่น IE จะแจกแจงรายการอาร์เรย์ตามลำดับที่เพิ่มเข้ามาไม่ใช่โดยดัชนี อย่างไรก็ตามคุณสามารถทำซ้ำได้อย่างถูกต้องเข้าถึงโดยดัชนี
Nick Craver

1
และนั่นแสดงให้เห็นถึงความแตกต่างระหว่างการระบุองค์ประกอบและการใช้ดัชนีเพื่อทำซ้ำ นี่คือเหตุผลที่เรามีทั้งแนวคิด คุณสามารถระบุค่าในรายการที่เชื่อมโยงหรือคุณสามารถรวบรวมข้อมูลรายการที่เชื่อมโยงและส่งคืนค่าจากหนึ่งไปยังอีก หนึ่งคือแนวคิดทางคณิตศาสตร์หนึ่งคือการสอนขั้นตอน
jcolebrand

1
@Pointy ใช่! และเนื่องจากหลาย ๆ การค้นหา "ทำไม indexOf จึงไม่ทำงานบนอาเรย์ IE8" อาจอยู่ในระดับความซับซ้อนต่ำกว่า WRT ถึง js มันอาจเป็นประโยชน์ที่จะชี้ให้เห็นว่าสิ่งนี้เป็นข้อพิสูจน์ถึงคำตอบ หากทุกคนมีความเข้าใจอย่างลึกซึ้งเกี่ยวกับข้อมูลจำเพาะและความแตกต่างระหว่างการนำไปใช้งานเธรดเช่นนี้จะไม่มีอยู่จริง @Nick คุณตั้งสมมติฐานที่แข็งแกร่งเกี่ยวกับความถูกต้อง มีการดำเนินการหลายอย่างที่คำสั่งไม่สำคัญ (เช่นตั้งค่าความแตกต่าง) นอกจากนี้ความคิดเห็นดั้งเดิมไม่ได้กล่าวถึงการแจกแจงในดัชนีลำดับเพียงว่าสำหรับ / ในนั้นมี user def fn อยู่ด้วย
สเปน Train

152

หากคุณใช้ jQuery คุณสามารถใช้$ .inArray ()แทน


7
ฉันเห็นด้วยว่าสิ่งนี้มีประโยชน์มากกว่า นั่นเป็นหนึ่งในเหตุผลหลักในการใช้ JQuery - มีหลายสิ่งที่ช่วยลดความไม่ลงรอยกันของเบราว์เซอร์ข้าม
cw24

17

หากคุณใช้jQueryและต้องการใช้ indexOf ต่อไปโดยไม่ต้องกังวลเกี่ยวกับปัญหาความเข้ากันได้คุณสามารถทำสิ่งนี้ได้:

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

สิ่งนี้มีประโยชน์เมื่อคุณต้องการใช้ต่อไปindexOfแต่จะให้ทางเลือกเมื่อไม่สามารถใช้งานได้


ใช่อาจเป็นเพราะเขาไม่ได้รวม jQuery ¯_ (ツ) _ / ¯เป็นไวยากรณ์ที่ถูกต้อง

10

สำหรับคำอธิบายอย่างละเอียดและวิธีแก้ปัญหาอย่างแท้จริงไม่เพียง แต่สำหรับ indexOf แต่ฟังก์ชันอาเรย์อื่น ๆ ที่ขาดหายไปใน IE ลองดูที่คำถาม StackOverflow การแก้ไขฟังก์ชั่น JavaScript Array ใน Internet Explorer (indexOf, forEach ฯลฯ )


5

โปรดใช้ความระมัดระวังกับ $. inArray หากคุณต้องการใช้ ฉันเพิ่งพบว่า $. inArray นั้นใช้ได้กับ "Array" เท่านั้นไม่ใช่กับ String นั่นเป็นเหตุผลที่ฟังก์ชั่นนี้จะไม่ทำงานใน IE8!

jQuery API สร้างความสับสน

วิธี $ .inArray () คล้ายกับเมธอด. indexOf () ดั้งเดิมของ JavaScript ซึ่งจะส่งคืน -1 เมื่อไม่พบข้อมูลที่ตรงกัน ถ้าองค์ประกอบแรกภายในอาร์เรย์จับคู่กับค่า $ .inArray () จะคืนค่า 0

-> พวกเขาไม่ควรพูดว่า "คล้ายกัน" เนื่องจาก indexOf รองรับ "String" ด้วย!


16
inArrayมันเรียกว่า นั่นดูเหมือนจะค่อนข้างชัดเจนว่าจะใช้กับอาร์เรย์เท่านั้น นั่นเป็นเหตุผลที่มัน "คล้ายกับ" และไม่ "เหมือนกัน"
tandrewnichols

ทราบดี ข้อเท็จจริงที่ตลกคือindexOfในวัตถุ String ถูกพบอย่างสมบูรณ์ใน IE ในขณะที่indexOfใน Array prototype ไม่พบใน IE <= 8
adi518

คุณกำลังผูกมันไว้กับชุดต้นแบบอาร์เรย์ดังนั้นมันจะไม่ส่งผลกระทบต่อสตริง
kagronick

3

ปัญหา

IE <= 8 ไม่มีindexOf()วิธีการสำหรับอาร์เรย์


การแก้ไขปัญหา

หากคุณต้องการindexOfใน IE <= 8 คุณควรพิจารณาใช้polyfillต่อไปนี้ซึ่งแนะนำที่ 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;
    };
}

ย่อขนาด:

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

คุณสามารถใช้ฟังก์ชันนี้เพื่อแทนที่ฟังก์ชั่นหากไม่มีอยู่:

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