前提
配列と、
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
重い処理の関数があって、
const slowFunction = x => {
console.log(`slowFunction called with ${x}`);
return x;
}
これを配列の先頭から適用して、その結果を判定するという繰り返し処理があったとして、
const isOK = x => {
return x > 5;
}
判定関数で有効なものをひとつでも取得できればそれでいい場合、途中で処理を打ち切りたい時、どう書くか、という話です。
Array.prototype.reduce
とかを使ってしまうと最後まで走査してしまいますし、Array.prototype.some
は途中で停止できますが処理後の値を取得することができないです。
結論
Iterator Helper が素敵。
今までのコード
おそらく、ループを使ってこんな感じで書くか、
let result = null;
for (let i = 0; !isOK(result) && i < arr.length; i++, result = slowFunction(arr[i])) { } // breakでもよい
console.log(result);
Array.prototype.some
などの関数の副作用を使って書くか、
let result = null;
arr.some(x => { // findでもよい
result = slowFunction(x);
return isOK(result);
});
console.log(result);
という感じだったかと思います。
いずれにせよ、テンポラリ変数をlet
で準備しなくてはいけない、というのはちょっとダサい感じがします。
まさかの時の Iterator Helper
これからはこう書けます。
arr.values().map(slowFunction).filter(isOK).take(1).toArray()[0]
遅延評価(?)してくれるので、必要のない関数呼び出しはしないのが素敵。
See the Pen Untitled by lhankor_mhy (@lhankor_mhy) on CodePen.
他の言語ではわりと当たり前だと思うのですが、JavaScriptは2025年になってようやく実装がそろってきました。