Internet ExplorerブラウザーのJavaScriptでArray indexOf()を修正する方法


295

任意の長さでJavaScriptを使用したことがある場合は、Internet ExplorerがArray.prototype.indexOf()[Internet Explorer 8を含む]のECMAScript関数を実装していないことに気づいています。次のコードを使用してページの機能を拡張できるため、これは大きな問題ではありません。

Array.prototype.indexOf = function(obj, start) {
     for (var i = (start || 0), j = this.length; i < j; i++) {
         if (this[i] === obj) { return i; }
     }
     return -1;
}

これはいつ実装すべきですか?

プロトタイプ関数が存在するかどうかをチェックする次のチェックですべてのページにラップする必要があります。存在しない場合は、先に進んで配列プロトタイプを拡張しますか?

if (!Array.prototype.indexOf) {

    // Implement function here

}

または、ブラウザチェックを行い、それがInternet Explorerである場合は、実装するだけですか?

//Pseudo-code

if (browser == IE Style Browser) {

     // Implement function here

}

実際にArray.prototype.indexOfはECMA-262 / ECMAScriptの一部ではありません。ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdfを参照してくださいたぶん、あなたは考えていString.prototype.indexOfます...
Crescent Fresh

5
これは拡張機能であり、元の標準の一部ではありません。しかし、(IEがする失敗した)のJavascript 1.6の一部として実装する必要がありdeveloper.mozilla.org/en/New_in_JavaScript_1.6
ジョシュStodola

1
@ジョシュ:「IEはECMAScript関数を実装していません...」
クレセントフレッシュ

4
の実装でArray.indexOfは、負の開始インデックスは考慮されません。:ここではMozillaの提案ストップギャップの実装を参照してくださいdeveloper.mozilla.org/en/JavaScript/Reference/Global_Objects/...
nickf

3
「===」を使用するように質問を更新しました。これは、「==」を使用してコピーされるのではないかと心配しているためです。Eli Greyの回答を参照してください。
joshcomley

回答:


213

このようにしてください...

if (!Array.prototype.indexOf) {

}

MDCでの互換性をお勧めします

一般的に、ブラウザー検出コードは大したことではありません。


質問を編集するのに十分な担当者がいませんが、ECMAScriptの専門用語を削除して適切な表現に置き換えてください。おかげで再び
ボビーBorszich 2009年

12
この種の検出を使用する場合は注意してください。テストする前に別のライブラリがこの関数を実装している可能性があり、標準に準拠していない可能性があります(プロトタイプが少し前にそれを実行しました)。私が敵対的な環境(多くの異なるライブラリを使用する他の多くのプログラマー)で作業している場合、これらのどれも信用できません...
Pablo Cabrera

「リンク」列--->は本当に便利です。私はここで答えを愛して: stackoverflow.com/questions/1744310/...
ゴードン・

すべてのjsファイルでラップする必要がありますか?
rd22、2016

MDCとは正確には誰ですか?
Ferrybig 2018

141

または、jQuery 1.2のinArray関数を使用することもできます。これは、ブラウザー間で機能します。

jQuery.inArray( value, array [, fromIndex ] )

'indexOf'はネイティブコード(右)なので、jQueryの 'inArray()'は同じくらい高速になりますか?
Jeach 2013年

10
私のコメント(上記)に答えるには、実装しました。Chromeでは 'indexOf()'を使用していたときと同じくらい高速ですが、IE 8では非常に遅くなります...少なくとも'inArray()'は、可能な場合はネイティブを使用します。
Jeach 2013年

78

完全なコードは次のようになります:

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(obj, start) {
         for (var i = (start || 0), j = this.length; i < j; i++) {
             if (this[i] === obj) { return i; }
         }
         return -1;
    }
}

これに対する本当に完全な回答とコード、および他の配列関数については、スタックオーバーフローの質問Internet ExplorerでのJavaScript配列関数の修正(indexOf、forEachなど)を確認してください。


2
いっぱい食べてくれてありがとう 新しいプロジェクトでクロスプラットフォームのindexOfが必要なときはいつでもこのページに頻繁にアクセスします。あなたのスニペットは完全なコードを持つ唯一のものです。:)これらの数秒は、このページに頻繁にアクセスすると実際に加算されます。
dylnmc 2017年


10

を使用して定義されていないかどうかを確認する必要がありif (!Array.prototype.indexOf)ます。

また、の実装がindexOf正しくありません。ステートメント=====はなくを使用する必要がありますif (this[i] == obj)。そうでない場合[4,"5"].indexOf(5)、実装によっては1になりますが、これは誤りです。

MDCの実装を使用することをお勧めします。


9

Mozilla公式ソリューションがあります:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

(function() {
    /**Array*/
    // Production steps of ECMA-262, Edition 5, 15.4.4.14
    // Reference: http://es5.github.io/#x15.4.4.14
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(searchElement, fromIndex) {
            var k;
            // 1. Let O be the result of calling ToObject passing
            //    the this value as the argument.
            if (null === this || undefined === this) {
                throw new TypeError('"this" is null or not defined');
            }
            var O = Object(this);
            // 2. Let lenValue be the result of calling the Get
            //    internal method of O with the argument "length".
            // 3. Let len be ToUint32(lenValue).
            var len = O.length >>> 0;
            // 4. If len is 0, return -1.
            if (len === 0) {
                return -1;
            }
            // 5. If argument fromIndex was passed let n be
            //    ToInteger(fromIndex); else let n be 0.
            var n = +fromIndex || 0;
            if (Math.abs(n) === Infinity) {
                n = 0;
            }
            // 6. If n >= len, return -1.
            if (n >= len) {
                return -1;
            }
            // 7. If n >= 0, then Let k be n.
            // 8. Else, n<0, Let k be len - abs(n).
            //    If k is less than 0, then let k be 0.
            k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
            // 9. Repeat, while k < len
            while (k < len) {
                // a. Let Pk be ToString(k).
                //   This is implicit for LHS operands of the in operator
                // b. Let kPresent be the result of calling the
                //    HasProperty internal method of O with argument Pk.
                //   This step can be combined with c
                // c. If kPresent is true, then
                //    i.  Let elementK be the result of calling the Get
                //        internal method of O with the argument ToString(k).
                //   ii.  Let same be the result of applying the
                //        Strict Equality Comparison Algorithm to
                //        searchElement and elementK.
                //  iii.  If same is true, return k.
                if (k in O && O[k] === searchElement) {
                    return k;
                }
                k++;
            }
            return -1;
        };
    }
})();

1
ただの独断的ですが、MDNはMozillaだけではありません。これはコミュニティ主導のプロジェクトであり、Mozillaのスタッフだけでなくボランティアも含まれており、誰でも参加して貢献できます。
ste2425 2016年


2

これは私の実装でした。基本的に、これをページ上の他のスクリプトの前に追加します。つまり、Internet Explorer 8のグローバルソリューションのマスターです。割り当て機能で使用されているように見えるトリム機能も追加しました。

<!--[if lte IE 8]>
<script>
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(obj, start) {
            for (var i = (start || 0), j = this.length; i < j; i++) {
                if (this[i] === obj) {
                    return i;
                }
            }
            return -1;
        };
    }

    if(typeof String.prototype.trim !== 'function') {
        String.prototype.trim = function() {
            return this.replace(/^\s+|\s+$/g, '');
        };
    };
</script>
<![endif]-->

2

わたしにはできる。

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

1

Underscore.js

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

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