find() は条件に合う最初の要素を返します。見つからなければ undefined です。途中で止まること、空振りの扱い、findIndex や filter との違いを実行して確かめます。
find() は、条件に合う最初の1件を返します。
見つからなければ undefined です。例外は投げません。
example.js
const users = [
{ id: 1, name: 'あかり' },
{ id: 2, name: 'ゆうと' },
];
console.log(users.find(u => u.id === 2));
console.log(users.find(u => u.id === 9));
出力書き換えて実行できます
{ id: 2, name: 'ゆうと' }
undefined
example.js
const nums = [1, 2, 3, 4, 5];
let calls = 0;
const found = nums.find((n) => {
calls++;
return n === 2;
});
console.log(found);
console.log('呼ばれた回数:', calls);
出力書き換えて実行できます
2
呼ばれた回数: 2
上のコードは書き換えて実行できます。u.id === 9 を u.id === 1 にしてみてください。
何が返るのか
|
中身 |
| 戻り値 |
条件に合った要素そのもの(配列ではない) |
| 見つからないとき |
undefined(null でも空配列でもない) |
| 元の配列 |
変わらない |
| どこまで見るか |
見つかった時点で止まる |
見つかったところで止まる
最後まで見ません。実際に数えて確かめます。
javascript
const users = [{ id: 1, name: 'あかり' }];
const user = users.find(u => u.id === 2);
console.log(user.name);
TypeError: Cannot read properties of undefined (reading 'name')
example.js
const users = [{ id: 1, name: 'あかり' }];
const user = users.find(u => u.id === 2);
console.log(user?.name);
console.log(user?.name ?? '(未登録)');
console.log(user ? user.name : '見つかりません');
出力書き換えて実行できます
undefined
(未登録)
見つかりません
5件あるのに2回しか呼ばれていません。これを短絡評価と呼びます。
要素が多いほど効きます。
空振りに必ず備える
find() を使うときにいちばん多い事故がこれです。
example.js
const fruits = ['りんご', 'みかん', 'ぶどう'];
console.log(fruits.findIndex(f => f === 'みかん'));
console.log(fruits.findIndex(f => f === 'かき'));
出力書き換えて実行できます
1
-1
javascript
const fruits = ['りんご', 'みかん'];
const i = fruits.findIndex(f => f === 'かき');
if (i) {
console.log('見つかった扱いになる:', i);
}
見つかった扱いになる: -1
undefined にプロパティは無いので落ちます。
見つからなかったときにどうするかを、その場で決めてください。
example.js
const nums = [1, 2, 3, 2];
console.log(nums.find(n => n === 2));
console.log(nums.findIndex(n => n === 2));
console.log(nums.findLast(n => n === 2));
console.log(nums.filter(n => n === 2));
console.log(nums.includes(2));
console.log(nums.indexOf(2));
出力書き換えて実行できます
2
1
2
[ 2, 2 ]
true
1
example.js
const sparse = [1, , 3];
let calls = 0;
sparse.find(() => { calls++; return false; });
console.log('find :', calls);
calls = 0;
sparse.filter(() => { calls++; return false; });
console.log('filter :', calls);
出力書き換えて実行できます
find : 3
filter : 2
詳しい直しかたは
Cannot read properties of undefined にあります。
位置が欲しいときは findIndex
要素そのものではなく何番目かが欲しいときに使います。
見つからないときは -1 です。
example.js
const nums = [1, 5, 3, 5, 2];
console.log(nums.find((n) => n === 5));
console.log(nums.findIndex((n) => n === 5));
console.log(nums.findLast((n) => n === 5));
console.log(nums.findLastIndex((n) => n === 5));
出力書き換えて実行できます
5
1
5
3
example.js
const nums = [1, 5, 3];
console.log(nums.findLast((n) => n === 9));
console.log(nums.findLastIndex((n) => n === 9));
出力書き換えて実行できます
undefined
-1
-1 は falsy ではありません。 if (i) で判定すると見つかったことになってしまいます。
example.js
const nums = [1, NaN, 3];
console.log(nums.indexOf(NaN));
console.log(nums.findIndex(Number.isNaN));
console.log(nums.includes(NaN));
出力書き換えて実行できます
-1
1
true
if (i !== -1) と書いてください。
0 番目に見つかった場合も if (i) では falsy になるため、二重に間違えます。
似ているものとの違い
|
何を返すか |
見つからないとき |
条件を書けるか |
find() |
最初の要素 |
undefined |
書ける |
findIndex() |
最初の位置 |
-1 |
書ける |
findLast() |
最後の要素 |
undefined |
書ける |
filter() |
配列(全部) |
空配列 |
書ける |
includes() |
真偽値 |
false |
値の一致だけ |
indexOf() |
最初の位置 |
-1 |
値の一致だけ |
「あるかどうか」だけ知りたいなら
includes() のほうが意図が伝わります。
filter() は全部要るときに使います。
穴のある配列でも呼ばれる
map() や filter() は疎な配列の穴を飛ばしますが、find() は飛ばしません。
穴を undefined として関数に渡します。
find() は3回、filter() は2回です。
穴を「値が無い場所」と見るか「undefined がある場所」と見るかが違います。
ふだん穴のある配列は作りませんが、length に代入したときなどにできます。
後ろから探す
findLast() と findLastIndex() は、末尾から探します(ES2023)。
値は同じでも、見つかった位置が違います。
「最後に更新されたもの」「いちばん新しい記録」を取りたいときに使います。
見つからないときの返り値は、前から探すときと同じです。
Node 20 / Chrome 97 / Safari 15.4 より前の環境では使えません。
NaN は indexOf() で見つからない
indexOf() は === で比べるので、NaN を見つけられません。
findIndex() に Number.isNaN を渡すか、あるかどうかだけなら includes() を使います。
→ なぜ NaN === NaN は false なのか
まとめ
find() は最初に見つかった要素。無ければ undefined
findIndex() は位置。無ければ-1
undefined は「無かった」とは限らない。 位置が要るなら findIndex()
- 見つかった時点で止まる。全部見たいなら
filter()
- 後ろから探すなら
findLast() / findLastIndex()
NaN を探すなら indexOf() ではなく findIndex(Number.isNaN)