JavaScript（ES6〜）暗黙的な型変換

## 暗黙的な型変換とは
自動的に異なる型の値を変換して演算や比較を行うこと
よって、等価演算子ではなく、厳密等価演算子( `===` )を使うようことで、暗黙的な型変換はできる限り避けてください

```javascript
console.log(5 == "5");  // true (文字列 "5" が数値に変換されて比較されます)
console.log(1 + true);  // 2
```

## 明示的な型変換
### 任意の値→真偽値
`Boolean`のコンストラクタ関数を使うと、任意の値を`true`または`false`に変換できます
JavaScriptではfalsyな値かそうでないかで`false`、`true`が決まります
- falsyな値は`false`に変換
- falsyでない値は`true`に変換
- falsyな値の一覧
    - null
    - undefined
    - false
    - NaN
    - 0
    - 0n
    - “” (空文字列)
```javascript
Boolean("super"); //  true
Boolean(1); //  true
Boolean({}); //  true
Boolean(null); //  false
Boolean(0); //  false
Boolean(""); //  false
```

### 数値→文字列
文字列を数値に明示的に変換する場合は、`String`コンストラクタ関数を使用します
```javascript
String("super"); //  "super"
String(null); // "null"
```

### シンボル→文字列
シンボルを文字列に明示的に変換する場合は、`String`コンストラクタ関数を使用します
```javascript
const sym = Symbol("example");
console.log(String(sym));  // "Symbol(example)"
```

### 文字列→数値
文字列を数値に明示的に変換する場合は、`Number`コンストラクタ関数を使用します
```javascript
const a = "64";

const num = Number(a);
console.log(typeof num); //  number
```

- Number.parseInt: 文字列を解析して整数に変換します
  - 第二引数には基数を指定します。10進数の場合は｢10｣
- Number.parseFloat: 文字列を解析して浮動小数点に変換します

```javascript
console.log(Number.parseInt("42px"));     // 42 (数値の部分だけ取得)
console.log(Number.parseInt("abc42"));    // NaN (先頭が数値でない場合はNaN)
console.log(Number.parseInt("1010", 2));  // 10 (2進数として解釈)

console.log(Number.parseFloat("42px"));      // 42 (数値の部分だけ取得)
console.log(Number.parseFloat("3.14abc"));   // 3.14 (数値の部分だけ取得)
console.log(Number.parseFloat("1.23e2"));    // 123 (指数表記も解釈)
```

## NaNとは
NaNは`Not a Number`の略で特殊な性質を持つNumber型のデータ
```javascript
console.log(typeof NaN); //  number
```
### NaNは何と演算しても、結果はNaN
```javascript
console.log(NaN + 10);  // NaN
```

### NaNは自分自身と一致しない
```javascript
console.log(NaN === NaN);  // false
```

### NaNであるかの判定方法
```javascript
Number.isNaN(NaN); // => true
```

### NaNへの変換の回避方法
NaNは何と演算しても結果がNaNとなり、不具合の原因になりやすいです
よって、その回避方法として、大きく分けて2つの方法があります
- sum関数内で、Number型以外の値を受け付けないようにする
```javascript
function sum(a, b) {
  if (typeof a !== 'number' || typeof b !== 'number') {
    throw new Error("Both arguments must be numbers.");
  }
  return a + b;
}

try {
  console.log(sum(10, 20));   // 30
  console.log(sum(10, '20')); // Error: Both arguments must be numbers.
} catch (error) {
  console.error(error.message);
}
```
- sum関数を呼び出す際に、Number型の値のみを渡すようにする
```javascript
function sum(a, b) {
  return a + b;
}

const a = 10;
const b = 20;

if (typeof a === 'number' && typeof b === 'number') {
  console.log(sum(a, b)); // 30
} else {
  console.error("Both arguments must be numbers.");
}
```

## 明示的な変換でも解決しないこと
数値に変換できない文字列を数値に変換しようとすると、結果は`NaN`になるなど

### 文字列が空文字列かどうかを判定
下記の場合、空文字列のみを判定することはできず、他のfalsyな値も引っかかってしまい、意図しない挙動になることがあります
```javascript
// falsyな値かどうかを判定(空文字列も判定)
function isEmptyString(str) {
    return !Boolean(str);
}

// 空文字列の場合
console.log(isEmptyString("")); //  true
// falsyな値の場合
console.log(isEmptyString(0)); //  true
```
#### 回避方法
空文字列とはString型で文字長が0の値であると定義することで、空文字列のみを判定することができます
```javascript
// 空文字列のみを判定
function isEmptyString(str) {
    return typeof str === "string" && str.length === 0;
}
// 空文字列の場合
console.log(isEmptyString("")); // => true
// falsyな値の場合
console.log(isEmptyString(0)); // => false
```

## まとめ
JavaScriptでは、異なる型の値が自動的に変換される暗黙的な型変換が発生するため、意図しない挙動を避けるために厳密等価演算子（ `===` ）を使用し、明示的な型変換を活用することが推奨されます。特にNaNの扱いやfalsyな値の判定には注意が必要で、適切な型チェックを行うことでバグを防ぐことができます。