ウェブサイト検索

javascript - Array.prototype.includes と Array.prototype.indexOf


可読性が向上することを除けば、includesにはindexOfに対して何か利点はありますか? 私には同じに見えます。

これの違いは何ですか

var x = [1,2,3].indexOf(1) > -1; //true

そしてこれは?

var y = [1,2,3].includes(1); //true

回答 #1

要点: NaN は異なる扱いをされます:

  • [NaN].indexOf(NaN) > -1 は false です
  • [NaN].includes(NaN) は true です

提案から:

動機

ECMAScriptの配列を使用する場合、配列に要素が含まれているかどうかを判定したいことがよくあります。これに対する一般的なパターンは次の通りです

if (arr.indexOf(el) !== -1) {
    ...
}

さまざまな他の可能性もあり、例えば arr.indexOf(el) >= 0 や、あるいは ~arr.indexOf(el) などです。

これらのパターンには二つの問題があります:

  • 彼らは「言いたいことを言う」ことに失敗しています:配列がある要素を含むかどうかを尋ねる代わりに、その要素が配列内で最初に出現するインデックスを尋ね、それを比較したりビット操作したりして、実際の質問の答えを決定します。
  • それらは NaN では失敗します。なぜなら indexOf は厳密等価比較を使用するため、[NaN].indexOf(NaN) === -1 となるからです。

提案された解決策

上記のパターンを次のように書き換えられるように、Array.prototype.includes メソッドの追加を提案します

if (arr.includes(el)) {
    ...
}

これは上記とほとんど同じ意味を持っていますが、Strict Equality Comparison の代わりに SameValueZero 比較アルゴリズムを使用しているため、[NaN].includes(NaN) が true になります。

したがって、この提案は既存のコードで見られる両方の問題を解決します。

私たちはさらに、整合性を保つために、Array.prototype.indexOfやString.prototype.includesと同様に、fromIndexパラメータを追加します。

さらに詳しい情報:

  • SameValueZero アルゴリズム
  • 「厳密等価比較」アルゴリズム

回答 #2

技術的に

  • NaN または undefined は、indexOf を使用した場合、見つけることができません。
[NaN].indexOf(NaN) // => -1 (not found)
[NaN].includes(NaN) // => true

[undefined].indexOf(undefined) // => -1 (not found)
[undefined].includes(undefined) // => true
  • includes は、要素がどのインデックスで見つかったかを知りたい場合には、役に立ちません。

  • 文字列を検索する際、includes は indexOf とは異なり正規表現を受け入れる

可読性

  • `arr.includes('searchedElement')` は言われている通りのことを行い、boolean を返すことは明らかです。
  • 文字列や配列に何かが存在するかを知るために arr.indexOf('searchedElement') !== -1 を使うことは、あまり読みやすくない。

パフォーマンス

この記事によると、目立った違いはないが、includes の方がわずかに遅いかもしれない。

歴史

indexOf は includes よりずっと前に作られました。

ブラウザのサポート

  • indexOf => 97.08%
  • 含む=> 97.51%

したがって、両方とも安全に使用できます。

回答 #3

.indexOf() と .includes() メソッドは、配列の要素を検索したり、指定された文字列内の文字や部分文字列を検索するために使用できます。

配列での使用

(ECMAScript仕様へのリンク)

  1. `indexOf` は厳密等価比較を使用するのに対し、`includes` は SameValueZero アルゴリズムを使用します。このため、次の2つの違いが生じます。

  2. フェリックス・クリングが指摘したように、NaNの場合は挙動が異なります。

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
  1. この動作は、undefined の場合でも異なります。
let arr = [ , , ];

arr.indexOf(undefined); // returns -1; meaning undefined is not present
arr.includes(undefined); // returns true

文字列での使用

(ECMAScript仕様へのリンク)

1. indexOf に正規表現(RegExp)を渡すと、正規表現は文字列として扱われ、見つかった場合はその文字列のインデックスを返します。しかし、includes に正規表現を渡すと、例外が発生します。

let str = "javascript";

str.indexOf(/\w/); // returns -1 even though the elements match the regex because /\w/ is treated as string
str.includes(/\w/); // throws TypeError: First argument to String.prototype.includes must not be a regular expression

パフォーマンス

GLAND_PROPREが指摘したように、includesはindexOfよりも少し(非常にわずかに)遅いかもしれません(最初の引数として正規表現をチェックする必要があるため)が、実際にはほとんど差はなく、無視できる程度です。

歴史

String.prototype.includes() は ECMAScript 2015 で導入されましたが、Array.prototype.includes() は ECMAScript 2016 で導入されました。ブラウザのサポートに関しては、賢く使用してください。

String.prototype.indexOf() と Array.prototype.indexOf() は ECMAScript の ES5 版に存在するため、すべてのブラウザでサポートされています。

関連記事