Edited at

JavaScript の Array.some と Array.includes の使い分け、値・参照型の動作の違い

More than 1 year has passed since last update.

JavaScript の Array.someArray.includes は、

どちらも配列に特定の要素が存在するか判定するのに使えます。

Array.someArray.includesをどのように使い分ければいいのかを考えたいと思います。



古えの JavaScript では...

ES2015 でArray.someが追加されるまで、配列にある要素が存在するか判定するには、

(本来の用途と違うため)直感的でないindexOfや、for文で冗長な記述をする必要がありました。


const chars = ["a", "b", "d", "g", "h", "i", "m", "n"];
const target = "d";

// for 文でループして探す
let exists = false;
for (const char of chars) {
if (char === target) {
exists = true;
break;
}
}
console.log(exists);

// インデックスが 0 より大きかったら存在する
exists = chars.indexOf(target) >= 0;
console.log(exists);



Array.someArray.includes の実装後

ES2015 でArray.some、ES2017でArray.includesが追加されました。

どちらも配列に特定の要素が含まれるかを直感的・簡潔に書くことができます。

includesは特定の要素が配列に含まれているかどうかをtrue / false で返します。

const chars = ["a", "b", "d", "g", "h", "i", "m", "n"];

const target = "d";

const exists = chars.includes(target);
console.log(exists); // => true

someは配列の少なくとも1つの要素が、渡されたテスト関数を通るかどうかをtrue / false で返します。

const chars = ["a", "b", "d", "g", "h", "i", "m", "n"];

const target = "d";

const exists = chars.some(c => c === target);
console.log(exists);



オブジェクトの配列でArray.includesを使ってみる

Array.includesBookオブジェクトの配列から対象の本を探してみます。

const books = [

{ title: "幼年期の終り", author: "アーサー・C・クラーク" },
{ title: "1984年", author: "ジョージ・オーウェル" },
{ title: "われはロボット", author: "アイザック・アシモフ" }
];

const target = {
title: "1984年",
author: "ジョージ・オーウェル"
};

const includes = books.includes(target);
console.log(`includes: ${includes}`); // includes: false

同じオブジェクトがあるように見えますが、結果はfalseが返ります。



オブジェクトの比較は参照が比較される

オブジェクトを比較するとき、その比較は同じ参照を指しているかどうかがテストされます。

includesによる比較も同様です。

つまり、以下のようなコードならArray.includestrueを返します。

const books = [

{ title: "幼年期の終り", author: "アーサー・C・クラーク" },
{ title: "1984年", author: "ジョージ・オーウェル" },
{ title: "われはロボット", author: "アイザック・アシモフ" }
];

const target = books[1];
const includes = books.includes(target);
console.log(`includes: ${includes}`); // includes: true



要素がオブジェクトの配列にはArray.some

Array.someは引数にテスト関数を渡すことができます。

オブジェクトの値型のプロパティがすべて等しいか調べるテスト関数を渡すことで、

要素がオブジェクトの配列に特定の要素が含まれているかを簡単に調べることができます。

const books = [

{ title: "幼年期の終り", author: "アーサー・C・クラーク" },
{ title: "1984年", author: "ジョージ・オーウェル" },
{ title: "われはロボット", author: "アイザック・アシモフ" }
];

const target = {
title: "1984年",
author: "ジョージ・オーウェル"
};

const some = books.some(
b => b.title === target.title && b.author === target.author
);
console.log(`some: ${some}`); // some: true

Array.someは要素1つ1つに対しテスト関数を反復実行し、

テスト関数をパスする要素が見つかった時点でtrueを返し処理を終了します。



まとめ

要素が値型の配列にはArray.includes

要素が参照型の配列(または条件を詳しく指定したい時)にはArray.some

と使い分けるといいと思います。