JavaScript の for ループの代替品

## この記事は？

Python 版はこちら (言語が違う以外ほぼ同じ):

https://qiita.com/aKuad/items/7c2eaea24cb7da449734

JavaScript の Array において、「各要素に対してこうする」というコードを書く機会がしばしばあります。基本的な実装方法は、「要素数だけ `for` ループを回して処理」です。

しかし、`for` を用いずにそれを実現できるメソッドがあります。上手く使えると、コード量を削減し、より簡潔に記述することができます。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array

ただし、**可読性などの観点で、for のままのが良いシチュエーションもあるので注意。** 各要素に対して複雑な処理をするのであれば、`for` で書いた方が無難です。

## 前提知識 - アロー関数式

次の 3つの関数は、いずれも「引数を 2倍した値を返す」という動作で等価です。

```js
function (e) {
  return e*2;
}
```

```js
e => { return e*2; }
```

```js
// 関数の内容が return のみのとき、return も省略可
e => e*2
```

アロー関数式 `=>` を使用すると、`function` `return` を省略して書くことができます。

## Array 各要素に対し、任意の処理をする

例: 各要素を 2倍にする

```js
const input  = [1, 2, 3, 4];
const output = [];

for(let i = 0; i < input.length; i++) {
  output.push(input[i] * 2);
}
// output: [2, 4, 6, 8]
```

```js
const input  = [1, 2, 3, 4];
const output = input.map(e => e*2);
// output: [2, 4, 6, 8]
```

[`.map()`](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map) の引数に、処理内容を定義した関数を指定します。`1` を引数に関数 `e => e*2` が、次は `2` `3` `4` を引数にと繰り返します。その関数の帰り値が、出力される Array (ここでは `output`) の要素に入れられます。

例が単純すぎて味気無いですが、もう少し応用的な例としては `<input type="file" multiple>` に入力されたファイルのファイル名抽出とかが挙げられます。

```js
const files      = document.getElementById("any-input-element").files
const files_name = [];

for(i = 0; i < files.length; i++) {
  files_name.push(files[i].name);
}
```

```js
const files      = document.getElementById("any-input-element").files
const files_name = Array.from(files).map(e => e.name)
//                 ~~~~~~~~~~~~~~~~~
// .map を使うため、FileList から Array に変換
```

<details><summary>(2024/01/29 追記) ↑あまり良い例じゃなかったかも･･･</summary>

@juner さんより、コメントにてご指摘いただきました。`Array.from()` 自体に `.map()` 的な機能があるようです。

```js
const files_name = Array.from(files, e => e.name);
```

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/from

(言い訳すると、シンプルに知らなかった。あと `.map()` のサンプルで苦し紛れに思いついたのがコレだったんです･･･。)

</details>

## Array から特定条件の要素のみ取り出す

例: 偶数だけ取り出す

```js
const array      = [1, 2, 3, 4];
const array_even = [];

for(let i = 0; i < array.length; i++) {
  if((array[i] % 2) == 0) {
    array_even.push(array[i]);
  }
}
// array_even: [2, 4]
```

```js
const array      = [1, 2, 3, 4];
const array_even = array.filter(e => (e % 2) == 0);
// array_even: [2, 4]
```

`.map()` 同様、各要素に対して [`.filter()`](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) の引数に渡した関数が呼び出されます。今度は、関数の返り値が `true` なら出力 Array (ここでは `array_even`) に入れ、`false` なら除かれます。

## ある値が複数あるいずれかと一致するか

例: 入力されたワードが曜日であるか確認する

```js
const input           = "mon";
const day_of_the_week = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];

let is_input_true = false;
for(let i = 0; i < day_of_the_week.length; i++) {
  if(input === day_of_the_week[i]) {
    is_input_true = true;
    break;
  }
}
// is_input_true: true
```

```js
const input           = "mon";
const day_of_the_week = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];

let is_input_true = day_of_the_week.includes(input);
// is_input_true: true
```

[`.includes()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes) の引数に渡した値が、Array 内 (ここでは `day_of_the_week`) にあれば `true`、なければ `false` を返します。

## あとがき - 標準 API リファレンスを見てみよう

リーダブルコードにて、こんな旨のアドバイスがありました。(文はうろ覚え)

> たまに標準 API の仕様書を読んでみると良い。
> 全部完璧に覚える必要は無い。
> だが、何となく覚えておいたものが、急に役立つことがある。

実際、MDN で Array のメソッドを調べてみると、けっこう色々なメソッドがあるのが分かります。それを読んでいくと、「あれ？あの時に書いたやつ、このメソッドで一発･･･」なんて出会いがあるかも。