find() メソッドは、提供されたテスト関数を満たす配列内の 最初の要素 の 値 を返します。
このデモのソースファイルは GitHub リポジトリに格納されています。デモプロジェクトに協力したい場合は、 https://github.com/mdn/interactive-examples をクローンしてプルリクエストを送信してください。
- 配列内で見つかった要素の添字が必要な場合は、
findIndex()を使用してください。 - 値の添字を検索する必要がある場合は、
Array.prototype.indexOf()を使用してください。 (findIndex()と似ていますが、それぞれの要素の等価性はテスト関数ではなく値でチェックします。) - 配列内に値が存在するかどうかを調べる必要がある場合は、
Array.prototype.includes()を使用してください。
構文
arr.find(callback(element[, index[, array]])[, thisArg])
引数
callback- 配列内の各要素に対して実行する関数で、次の 3 つの引数を取ります。
element- 配列内で現在処理されている要素です。
indexOptional- 配列内で現在処理されている要素の添字 (位置) です。
arrayOptionalfindを呼び出した元の配列です。
thisArgOptionalcallback内でthisとして使われるオブジェクトです。
返値
配列の中で、提供されたテスト関数を満足する最初の要素の値です。見つからなかった場合は undefined を返します。
解説
find メソッドは、配列のそれぞれの添字に対して一度ずつ、 callback 関数を実行し、 callback 関数が truthy な値を返すまで繰り返します。その場合、 find は直ちにその要素の値を返します。そうでなければ、 find は undefined を返します。
callback は、値が割り当てられているものに限らず、配列中のすべての添字に対して呼び出されます。すなわち、疎配列では値が割り当てられているもののみを呼び出すメソッドに比べて効率的ではないことを意味します。
thisArg 引数が find に与えられた場合、 callback の呼び出しのたびに、その内部で this 値として使用されます。この引数を省略した場合は undefined が使用されます。
find は、呼び出した配列を変更 (mutate) しませんが、 callback で提供された関数は変更する可能性があります。その場合、 find によって処理される各要素は、最初に callback が呼び出される前に設定されます。したがって、
callbackはfindの呼び出しが始まった後に追加された要素に対しては実行されません。- 配列の、既存のまだ呼び出していない要素が
callbackによって変更された場合、callbackに渡される値はfindがその要素の添字を処理した時点での値になります。 削除された要素も処理されます。
例
配列内のオブジェクトをプロパティの一つで検索
const inventory = [
{name: 'apples', quantity: 2},
{name: 'bananas', quantity: 0},
{name: 'cherries', quantity: 5}
];
function isCherries(fruit) {
return fruit.name === 'cherries';
}
console.log(inventory.find(isCherries));
// { name: 'cherries', quantity: 5 }
アロー関数と分割の使用
const inventory = [
{name: 'apples', quantity: 2},
{name: 'bananas', quantity: 0},
{name: 'cherries', quantity: 5}
];
const result = inventory.find( ({ name }) => name === 'cherries' );
console.log(result) // { name: 'cherries', quantity: 5 }
配列内の素数の検索
次の例は、配列内の素数を探します (配列内に素数が見つからない場合は undefined を返します)。
function isPrime(element, index, array) {
let start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) {
return false;
}
}
return element > 1;
}
console.log([4, 6, 8, 12].find(isPrime)); // undefined, 見つからない
console.log([4, 5, 8, 12].find(isPrime)); // 5
以下の例は存在せず削除された要素が処理されること、コールバックに渡される値が処理時点での値であることを示しています。
// 添字が 2, 3, 4 の位置に要素がない配列を宣言
const array = [0,1,,,,5,6];
// 値が割り当てられているものに限らず、すべての添字を表示
array.find(function(value, index) {
console.log('Visited index ', index, ' with value ', value);
});
// 削除されたものを含め、すべての添字を表示
array.find(function(value, index) {
// 初回で要素 5 を削除
if (index === 0) {
console.log('Deleting array[5] with value ', array[5]);
delete array[5];
}
// 要素 5 は削除されても処理される
console.log('Visited index ', index, ' with value ', value);
});
// 期待される出力:
// Deleting array[5] with value 5
// Visited index 0 with value 0
// Visited index 1 with value 1
// Visited index 2 with value undefined
// Visited index 3 with value undefined
// Visited index 4 with value undefined
// Visited index 5 with value undefined
// Visited index 6 with value 6
ポリフィル
このメソッドは、 ECMAScript 2015 仕様書で追加されたものであり、すべての JavaScript 実装環境で使用できるとは限りません。しかし、 Array.prototype.find のポリフィルを以下のスニペットで使用できます。
// https://tc39.github.io/ecma262/#sec-array.prototype.find
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
value: function(predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw TypeError('"this" is null or not defined');
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw TypeError('predicate must be a function');
}
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];
// 5. Let k be 0.
var k = 0;
// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return kValue.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
// e. Increase k by 1.
k++;
}
// 7. Return undefined.
return undefined;
},
configurable: true,
writable: true
});
}
Object.defineProperty に対応していない、本当に古い JavaScript エンジンに対応する必要がある場合は、列挙不可に設定することができないため、 Array.prototype のポリフィルをまったく使用しないのが最善です。
仕様書
| 仕様書 | 状態 | 備考 |
|---|---|---|
| ECMAScript Latest Draft (ECMA-262) Array.prototype.find の定義 |
ドラフト | |
| ECMAScript 2015 (6th Edition, ECMA-262) Array.prototype.find の定義 |
標準 | 初回定義 |
ブラウザーの互換性
| デスクトップ | モバイル | サーバー | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
find | Chrome 完全対応 45 | Edge 完全対応 12 | Firefox 完全対応 25 | IE 未対応 なし | Opera 完全対応 32 | Safari 完全対応 8 | WebView Android 完全対応 あり | Chrome Android 完全対応 45 | Firefox Android 完全対応 4 | Opera Android 完全対応 あり | Safari iOS 完全対応 8 | Samsung Internet Android 完全対応 あり | nodejs
完全対応
4.0.0
|
凡例
- 完全対応
- 完全対応
- 未対応
- 未対応
- ユーザーが明示的にこの機能を有効にしなければなりません。
- ユーザーが明示的にこの機能を有効にしなければなりません。
関連情報
Array.prototype.findIndex()– 添字を検索して返すArray.prototype.includes()– 配列内に値が存在するかどうかをテストするArray.prototype.filter()– 一致しない要素をすべて削除するArray.prototype.every()– すべての要素をテストArray.prototype.some()– ある要素が一致するまでテスト