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

IE9より前のバージョンのIEには、.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;
  };
}

これは、Firefox / SpiderMonkeyで使用されているMDNのバージョンです。IEなどの他のケース.indexOf()では、欠落している場合に追加されます...この時点では基本的にIE8以下です。


2
あなた(または使用するライブラリ)がfor / in構文を使用して配列を列挙する場合(例:for(idx in arrayname)stmt;)、このメソッドも列挙されることに注意してください。これは、組み込みのプロパティがfor / inによって列挙されず、ユーザー定義のプロパティが列挙されるためです。
スペイン列車

5
@マイク-それは別の問題です... for...inループを使用して配列を反復するので なく、列挙のみに使用してください。
Nick Craver

3
@マイク-複数のブラウザー間で正しい順序で結果を取得するなどの理由により、配列を反復処理します。for..in配列での使用は問題を引き起こすだけであり、それは単なる規則ではありません。意図しない使用法であり、誤った使用法です。順序とキーはどちらも完全に指定されているわけではなく、実装に依存しています。たとえば、IEは配列の項目を、インデックスではなく追加された順序で列挙します。ただし、インデックスを使用してアクセスすることで、正しく反復できます。
Nick Craver

1
そして、それは要素を列挙することとインデックスを使用して繰り返すことの違いを示しています。これが、両方のコンセプトがある理由です。リンクリストの値を列挙するか、リンクリストをクロールして、値を次のリストに返すことができます。1つは数学的な概念で、もう1つは手続き型の命令です。
jcolebrand 2010年

1
@先のとがった!そして、多くの場合、「IE8が配列IE8で機能しないのはなぜですか?」WRTからjsへの高度化レベルが低い可能性があります。これは、答えの当然の結果として指摘するのに役立ちます。誰もが仕様と実装間の違いを深く理解していたら、このようなスレッドは存在しません。@ニックあなたは正しさについて強い仮定をします。順序が重要ではない多くの操作があります(たとえば、セットの違いなど)。また、元のコメントでは、インデックスシーケンスでの列挙については触れられていません。
スペイン列車

152

jQueryを使用している場合は、代わりに$ .inArray()を使用できます。


7
これはもっと便利だと思います。これがJQueryを使用する主な理由の1つです。クロスブラウザーの非互換性を軽減するために多くのことを行います。
cw24 2014年

17

jQueryを使用していて、互換性の問題を心配せずにindexOfを使い続けたい場合は、次のようにします。

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

これは、使い続けたい場合に役立ちますが、indexOf使用できない場合のフォールバックを提供します。


はい、おそらくjQueryを含めなかったためです¯_(ツ)_ /¯これは有効な構文です。


5

$ .inArrayを使用する場合は注意してください。$ .inArrayは「配列」でのみ機能し、文字列では機能しないことがわかりました。このため、この関数はIE8では機能しません。

jQuery APIは混乱を招く

$ .inArray()メソッドは、一致が見つからない場合に-1を返すという点でJavaScriptのネイティブの.indexOf()メソッドに似ています。配列内の最初の要素が値と一致する場合、$。inArray()は0を返します

->彼らはそれを「似ている」と言ってはいけません。indexOfは "String"もサポートしているので!


16
と呼ばれていinArrayます。これは、配列のみに適用するのはかなり断固としたようです。これが「類似」であり、「同一」ではない理由です。
tandrewnichols 2014年

良いメモ。面白い事実であるindexOfながら完全IEに見出される文字列オブジェクト内のindexOf配列のプロトタイプでIE <= 8で発見されていない
adi518

これを配列プロトタイプにバインドするので、文字列に影響を与えません。
kagronick 2016年

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>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.