Чому 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()функції для масиву, щоб визначити точну версію специфікації , запустіть це перед тим, як спробувати використовувати його:

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
Зауважте, що якщо ви (або використовувані вами бібліотеки) використовуєте синтаксис for / in для перерахування масивів (наприклад, для (idx у імені масиву) stmt;), цей метод також буде перерахований. Це тому, що вбудовані властивості не перераховуються за / в, але визначені користувачем.
Іспанія поїзд

5
@Mike - це інша проблема ... ви не повинні використовувати for...inцикл для ітерації масиву, він повинен використовуватися лише для перерахунку .
Нік Крейвер

3
@Mike - ви повторюєте масив з додаткових причин .. як-от отримання результатів у правильному порядку у веб-переглядачах. Використання for..inмасиву спричинить лише проблеми, це не просто умова .. це ненавмисне використання та неправильне використання. Порядок і ключі обидва не вказані повністю, вони залежать від реалізації ... наприклад, IE буде перераховувати елементи масиву в тому порядку, в який вони були додані , а не за їх індексом. Однак ви можете правильно повторити , звертаючись за індексом.
Нік Крейвер

1
І це ілюструє різницю між перерахуванням елементів та використанням індексу для повторення. Тому ми маємо обидва поняття. Можна перерахувати значення у зв'язаному списку, або ви можете сканувати зв'язаний список і повертати значення від одного до іншого. Один - математичне поняття, один - процедурна інструкція.
jcolebrand

1
@Pointy Так! А оскільки багато хто шукає "Чому indexOf не працює на масиві IE8?" може бути на нижчому рівні витонченості WRT до js, це може бути корисно вказати на це як відповідь на відповідь. Якби всі вже глибоко розуміли специфікацію та відмінності між реалізаціями, таких потоків не було б. @Nick Ви робите чіткі припущення щодо правильності. Існує багато операцій, для яких порядок не має значення (наприклад, встановити різницю.) Також в первісному коментарі не зазначалося перерахування в послідовності індексів, саме те, що для / в включає в себе користувача def fn.
Іспанія поїзд

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 ¯_ (ツ) _ / ¯ Це синтаксис.


5

Будьте обережні з $ .inArray, якщо ви хочете ним користуватися. Я щойно дізнався, що $ .inArray працює лише з "Array", а не з String. Ось чому ця функція не працюватиме в IE8!

API jQuery робить плутанину

Метод $ .inArray () схожий на початковий метод JavaScript .indexOf (), оскільки він повертає -1, коли не знаходить відповідності. Якщо перший елемент масиву відповідає значенню, $ .inArray () повертає 0

-> Вони не повинні говорити це "Схоже". Так як indexOf також підтримує "String"!


16
Це називається inArray. Це, здається, остаточно стосується лише масивів. Ось чому воно "схоже на", а не "тотожне".
tandrewnichols

Гарна примітка. Кумедний факт indexOfв тому, що об'єкт String повністю знайдений в IE, а indexOfв прототипі Array не знайдено в IE <= 8.
adi518

Ви прив'язуєте його до прототипу масиву, щоб він не впливав на рядки.
kagronick

3

Проблема

IE <= 8 просто не має indexOf()методу для масивів.


Рішення

Якщо вам потрібен indexOfIE <= 8, слід розглянути можливість використання наступної полісистеми , яка рекомендується в 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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.