【JavaScript】ifって何？

# if文とは
`if`文は**条件によって処理を変える**ための構文です。
条件分岐と呼ばれることもあります。

## 基本構文
`if`文は2つの要素から構成されます。

- 条件式: 処理をするかどうかを判定する真偽値
- 処理

構文はこんな感じです。

```js
if (条件式) {
  // 処理
}
```

例えば、`number`変数が`10`以上のときのみログ出力する処理が書けます。

```js
const number = 12
if (number >= 10) { // numberは12なのでtrue
  console.log('numberは10以上です')
}

// ログは出力される
```

```js
const number = 8
if (number >= 10) { // numberは8なのでfalse
  console.log('numberは10以上です')
}

// ログは出力されない
```

なお、ブロック（`{}`）は省略することもできます。
```js
if (条件式) 1行の処理

// 例
if (number >= 10) console.log('numberは10以上です')
```

## else
elseを使うと、条件式が`false`の場合に実行する処理を追加できます。

```js
if (条件式) {
  // trueの場合に実行される処理
} else {
  // falseの場合に実行される処理
}
```

### else if

また、`else if`を使うと、最初の条件が`false`だった場合の新しい条件を加えることができます。

```js
if (条件式1) {
  // 条件式1がtrueの場合に実行される処理
} else if (条件式2) {
  // 条件式1がfalseかつ、
  // 条件式2がtrueの場合に実行される処理
} else {
  // 条件式1がfalseかつ、
  // 条件式2がfalseの場合に実行される処理
}
```

同じ処理は`if`文の中に`if`文を書くことでもできます。

```js
if (条件式1) {
  // 条件式1がtrueの場合に実行される処理
} else { 
  if (条件式2) {
    // 条件式1がfalseかつ、
    // 条件式2がtrueの場合に実行される処理
  } else {
    // 条件式1がfalseかつ、
    // 条件式2がfalseの場合に実行される処理
  }
}
```

しかし、左側の余白が増える（ネストが深くなる）と**コードが読みづらくなってしまう**ことがあります。
そのため、使う機会は条件式1が`false`だった場合に共通の処理があるなど、結構限られてくるかもしれません。

```js
if (条件式1) {
  // 略
} else { 
  // 条件式1がfalseの場合に実行される、共通の処理
  if (条件式2) {
    // 略
  } else {
    // 略
  }
}
```

# 用途
ここからは`if`文の使い所を紹介します。

## 条件分岐
先ほども説明した通り、`if`文は条件に応じて処理を変えることができます。
これを**条件分岐**と呼ぶことがあります。

条件分岐はとにかくいろんなところで使えます。
例えばこれは、入力されたスコアに応じて出力されるログを変える処理です。

```js
// prompt関数で入力を受け取る
const score = parseInt(prompt())

if (score >= 90) {
  console.log('素晴らしい！');
} else if (score >= 75) {
  console.log('良い感じ！');
} else {
  console.log('もう少し頑張りましょう');
}
```

## 早期リターン
`if`文の活用方法として、**関数の早期リターン**があります。

早期リターンというのは、主に関数の最初のほうで処理したくない場合を検知し、早めにそれ以降の処理を中断することです。
もっと平たく言えば、最初の方に`if`文を使って`return`を書くことです。

```js
function sample() {
  if (条件式) return; // これが早期リターン
  // 処理
}
```

これは引数のチェックなどに使えます。

早期リターンを使うメリットとして、普通に`if`文を使うより**ネストが深くなりづらい**ことが挙げられます。
この普通の`if`文を使うというのは、例えばこんな感じのコードになります。

```js
function sample() {
  if (条件式) {
    // 通常の処理
    // この処理は数行以上ある
  }
  // ここには何の処理もない
}
```

このように書くと、通常の処理の部分のネストが深くなり、**コードが読みづらくなってしまう**ことがあります。
もちろん一概には言えないのですが、このように書くより、早期リターンを使ったほうが読みやすくなることは多いです。

```js
function sample() {
  if (条件式) return // 何の処理も必要ないので、returnで中断する
  // 通常の処理
  // この処理は数行以上ある
}
```

### 早期リターンの例

例えば、配列の数値の和を返す`sum`関数があります。
この関数は引数に配列を取ります。

また、以下の条件では配列の合計を計算しません。

- 長さが0の場合: `null`を返す
- 負の数が混ざっている場合: その数は足さない

このとき、早期リターンを使って以下のように実装できます。
（[`reduce`メソッドを使う手](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)もありますが、今回は`for`文で実装します。）

```js
function sum(array) {
  // 早期リターン1: 配列の長さが0ならnullを返す
  if (array.length === 0) return null
  
  let result = 0
  for (const num of array) {
    // 早期リターン(?)2: numが負の数なら何も足さない
    if (num) continue // 次のループに行く
    result += num
  }

  return result
}
```

こんなふうに最初に`return`などを持ってくることで、コードのネストが減って読みやすくなります。

:::note
早期リターンという言葉の定義は結構**曖昧**な印象があります。
そのため何が早期リターンかどうか定義するのは難しいです`、「これ早期リターンっぽいな」と言うことはできます。

この際、以下の場合でも早期リターンかもしれません。

- `return`ではなく`throw`などでエラーをスローしている
- `return`以外にいくつかの処理がある

- メイン処理がどうとかではなく、いろんな条件がたくさんある関数で`if`文をネストしない（[例](https://zenn.dev/media_engine/articles/early_return)）

とりあえず、メイン処理を`if`文の外に置いたりすることで、結果的にコードのネストを減らすテクニックがあるってことだけ知っていたらいいと思います。
:::

---

`if`文の詳細は[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/if...else)をご覧ください。
また、[こちら](https://x-tech.pasona.co.jp/media/detail.html?p=2619)には`if`文の解説のほかに**比較に使える演算子**の話もあります。

# 三項演算子
`if`文と似たような役割の構文として、三項演算子があります。
三項演算子は**条件によってどの値を使うか決められる式**です。

```js
// 条件がtrueなら値1、そうでないなら値2を使いたい
条件 ? 値1 : 値2
```

例えば、変数の値を条件に応じて変えるときに役立ちます。

```js
const score = 55
const result = (score >= 60) ? '合格' : '不合格';
console.log(`テストの結果は${result}です`)

// テストの結果は不合格です
```

詳細は[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Conditional_operator)をご覧ください。
また、[こちらの記事](https://www.bold.ne.jp/engineer-club/javascript-ternary-operator)もわかりやすいです。

## 三項演算子の問題

複雑な条件が続く場合に使いすぎると、**コードが読みづらくなる**という話があります。

例えば、以下のように2つの条件から3つの出力がある場合を想定します。
```js
const result = mathScore === 100
  ? scienceScore === 100
    ? '非常に素晴らしいです！'
    : '素晴らしいです！'
  : '数学で100点を目指しましょう'
```

どうでしょうか。簡単に読めましたか？
以下にこのコードの図解を用意しましたが、その前に一度読み解いてみてください。

```mermaid
flowchart TD
    S[const result =] --> A
    A{数学が100点か？} -->|Yes| B{理科が100点か？}
    A -->|No| C[数学で100点を目指しましょう]
    B -->|Yes| D[非常に素晴らしいです！]
    B -->|No| E[素晴らしいです！]
```

このコードはやたらと数学優位なメッセージを`result`に代入しています。
なので、もし理科で100点を取ったとしても「数学で100点を目指しましょう」が代入されます。

もし簡単に読めたという方でも、**これ以上ネストが増える**と読みづらくなってくると思います。
三項演算子はあまり**ネストしすぎず**、そして大きな処理を書きすぎないようにしましょう。
複雑な処理が必要になりそうなら**別の関数に分けて`if`文で書き直す**などの対策をとったほうがいいです。

---

ちなみに私は三項演算子が便利すぎて、ついついネストしてしまいます。
しかし今思えば、あの時書いたコードもあのコードも、すでに読める気がしません（手遅れ）。