.forEach()よりもfor-of派な理由 - JavaScript/TypeScript
#JavaScript #TypeScript
書きたいこと
Array.prototype.forEach()よりもfor-of(for (const e of arr))を好んで使っている理由を書きたい。
多少宗教的なことがあり、最近Rustだとfor_eachが好まれるというような話も目にして、開発者の背景などにも好みは依存すると思う。
for-of派な理由
再代入を抑制したい
arr.forEach(e => {})だと配列の要素のeに再代入できてしまう。
なるべく再代入される可能性を削減したいが現在のところTypeScriptで引数の再代入を禁止する方法はないはず。
それに対してfor-ofならfor (const e of arr)のようにconstを使って再代入を抑制できる。
async-awaitとの親和性
async-awaitと親和性がfor-ofの方が高いと思う。awaitを好きにforの内部に書ける。
code:js
for (const e of arr) {
await ...;
}
.forEach()でこれと同じことをするのは難しく、例えば以下は"hello"が先に出てあとから1, 2, 3がでるし、1と2の表示に1秒待つ動作にはならないがfor-ofだとそれはやりやすい。意図的に以下のようにしたいときは.forEach()を使えば良いと思う。
code:js
(async () => {
1, 2, 3.forEach(async (e) => {
await new Promise(resolve => setTimeout(resolve, 1000));
console.log(e);
});
console.log("hello");
})();
break/continueが使える
for-ofの方が、関数型慣れすると使わなくなる傾向はあるものの、あるとbreakとcontinueと手続き的思考をコードにする時に書きやすいことがある。
あと何かとJavaScriptの関数は厄介なことが多い印象があるのでコールバックを引数にとる.forEachよりもforを使いたくなる言語化できない気持ちがある。
おまけ: for-ofでインデックス欲しい
.entries()を使って、[idx, e] of ...のようにすれば良い。
code:js
for (const idx, e of "A", "B", "C".entries()) {
console.log(idx, e);
}