Array.prototype.find()

find() メソッドは、提供されたテスト関数を満たす配列内の 最初の要素 を返します。

  • 配列内で見つかった要素の添字が必要な場合は、 findIndex() を使用してください。
  • 値の添字を検索する必要がある場合は、 Array.prototype.indexOf() を使用してください。 (findIndex() と似ていますが、それぞれの要素の等価性はテスト関数ではなく値でチェックします。)
  • 配列内に値が存在するかどうかを調べる必要がある場合は、 Array.prototype.includes() を使用してください。

構文

arr.find(callback(element[, index[, array]])[, thisArg])

引数

callback
配列内の各要素に対して実行する関数で、次の 3 つの引数を取ります。
element
配列内で現在処理されている要素です。
index Optional
配列内で現在処理されている要素の添字 (位置) です。
array Optional
find を呼び出した元の配列です。
thisArg Optional
callback 内で this として使われるオブジェクトです。

返値

配列の中で、提供されたテスト関数を満足する最初の要素です。見つからなかった場合は undefined を返します。

解説

find メソッドは、配列のそれぞれの添字に対して一度ずつ、 callback 関数を実行し、 callback 関数が truthy な値を返すまで繰り返します。その場合、 find は直ちにその要素の値を返します。そうでなければ、 findundefined を返します。

callback は、値が割り当てられているものに限らず、配列中のすべての添字に対して呼び出されます。すなわち、疎配列では値が割り当てられているもののみを呼び出すメソッドに比べて効率的ではないことを意味します。

thisArg 引数が find に与えられた場合、 callback の呼び出しのたびに、その内部で this 値として使用されます。この引数を省略した場合は undefined が使用されます。

find は、呼び出した配列を変更 (mutate) しませんが、 callback で提供された関数は変更する可能性があります。その場合、 find によって処理される各要素は、最初に callback が呼び出される前に設定されます。したがって、

  • callbackfind の呼び出しが始まった後に追加された要素に対しては実行されません。
  • 配列の、既存のまだ呼び出していない要素が 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 の定義
標準 初回定義

ブラウザーの互換性

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung InternetNode.js
findChrome 完全対応 45Edge 完全対応 12Firefox 完全対応 25IE 未対応 なしOpera 完全対応 32Safari 完全対応 8WebView Android 完全対応 ありChrome Android 完全対応 45Firefox Android 完全対応 4Opera Android 完全対応 ありSafari iOS 完全対応 8Samsung Internet Android 完全対応 ありnodejs 完全対応 4.0.0
完全対応 4.0.0
完全対応 0.12
無効
無効 From version 0.12: this feature is behind the --harmony runtime flag.

凡例

完全対応  
完全対応
未対応  
未対応
ユーザーが明示的にこの機能を有効にしなければなりません。
ユーザーが明示的にこの機能を有効にしなければなりません。

関連情報