JavaScript 入門

JavaScript 型変換

型変換と型強制は、異なるデータ型の値がどのように相互作用し、変換されるかを決定します。

JavaScriptは弱型付け(Loosely typed)言語であり、これらの変換を自動的に実行することがよくあります。これは便利な反面、混乱の原因にもなり得ます。

本章では、明示的な型変換(Explicit Type Conversion)と、暗黙的な型変換(Implicit Type Coercion / 型強制)の複雑な仕組みを詳しく探求し、JavaScriptプログラムでデータ型を効率的に管理するための知識とツールを提供します。

1. 型変換 (Conversion) vs. 型強制 (Coercion)

これら2つの概念を区別することは非常に重要です。

  • 型変換 (Type Conversion / Explicit): 内蔵関数やメソッドを使用して、手動で値をある型から別の型へ変換することを指します。プログラマーが明示的にJavaScriptへ変換を指示します。
  • 型強制 (Type Coercion / Implicit): JavaScriptが異なるデータ型の値に対して操作を実行しようとする際、自動的に発生します。JavaScriptエンジンが操作を可能にするために、どのように値を変換するかを決定します。

この違いを理解することが、コードの振る舞いを予測する鍵となります。

2. 明示的な型変換

明示的な型変換を使用すると、値の変換方法をコントロールできます。JavaScriptはこのためにいくつかのビルトイン関数を提供しています。

2.1 数値 (Number) への変換

値を数値に変換する方法はいくつかあります。

2.1.1 Number() 関数

これは値を数値に変換するための主要な関数です。あらゆるデータ型をその数値表現に変換しようと試みます。

// ストリングを数値に変換
let str1 = "123";
let num1 = Number(str1);
console.log(num1); // 出力: 123 (Number)

let str2 = "3.14";
let num2 = Number(str2);
console.log(num2); // 出力: 3.14 (Number)

let str3 = "hello";
let num3 = Number(str3);
console.log(num3); // 出力: NaN (非数値)

let str4 = "";
let num4 = Number(str4);
console.log(num4); // 出力: 0 (空文字列は 0 に変換される)

// ブーリアンを数値に変換
console.log(Number(true));  // 出力: 1
console.log(Number(false)); // 出力: 0

// null と undefined を数値に変換
console.log(Number(null));      // 出力: 0
console.log(Number(undefined)); // 出力: NaN

2.1.2 parseInt() 関数

この関数は文字列をパース(解析)し、整数を返します。

  • 左から右へパースし、無効な数字文字に当たった時点で停止します。
  • 第2引数として radix(基数)を受け取り、進数を指定します(常にこの引数を提供することを強く推奨します)。
console.log(parseInt("10"));      // 出力: 10
console.log(parseInt("10.5"));    // 出力: 10 (小数点以下は切り捨て)
console.log(parseInt("10px"));    // 出.log(parseInt("10px"));    // 出力: 10 ('p' に当たった時点で停止)
console.log(parseInt("px10"));    // 出力: NaN (非数字で始まっている)
console.log(parseInt("1010", 2)); // 出力: 10 (2進数から10進数へ)

2.1.3 parseFloat() 関数

この関数は文字列をパースし、フローティングポイント(浮動小数点数)を返します。parseInt() と同様に、無効な文字に当たった時点でパースを停止します。

console.log(parseFloat("3.14"));    // 出力: 3.14
console.log(parseFloat("3.14px"));  // 出力: 3.14
console.log(parseFloat("  3.14  ")); // 出力: 3.14 (前後の空白は自動で除去される)

2.2 ストリング (String) への変換

2.2.1 String() 関数

あらゆる値を文字列に変換できます。

console.log(String(123));   // 出力: "123"
console.log(String(true));  // 出力: "true"
console.log(String(null));  // 出力: "null"
console.log(String(undefined)); // 出力: "undefined"

2.2.2 .toString() メソッド

ほとんどのJavaScriptオブジェクトはこのメソッドを持っています。
注意: nullundefined に対してこのメソッドを呼び出すとエラーになります。

let num = 123;
console.log(num.toString()); // 出力: "123"

let bool = true;
console.log(bool.toString()); // 出力: "true"

// null.toString(); // エラーをスロー (TypeError)

2.3 ブーリアン (Boolean) への変換

Boolean() 関数を使用すると、値をブーリアン型に変換できます。これはJavaScriptの論理判断を理解する上での核心です。

2.3.1 真値 (Truthy) と 偽値 (Falsy)

JavaScriptには、ブーリアンに変換した際に false と見なされる少数の「Falsy(偽値)」が存在します。それ以外のすべての値は「Truthy(真値)」です。

Falsy(偽値)リスト:

  1. false
  2. 0 (ゼロ)
  3. -0 (マイナスゼロ)
  4. 0n (BigInt ゼロ)
  5. "" (空文字列)
  6. null
  7. undefined
  8. NaN
console.log(Boolean(0));        // 出力: false
console.log(Boolean(""));       // 出力: false
console.log(Boolean(null));     // 出力: false

console.log(Boolean("hello"));  // 出力: true (非空文字列)
console.log(Boolean(123));      // 出力: true (非ゼロの数値)
console.log(Boolean([]));       // 出力: true (空の配列も Truthy)
console.log(Boolean({}));       // 出力: true (空のオブジェクトも Truthy)
console.log(Boolean("false"));  // 出力: true (文字列 "false" は非空なので Truthy)

3. 暗黙的型強制

型強制は、JavaScriptが自動的にデータ型を変換する際に発生します。ルールを知らないと、予期せぬ結果を招く可能性があります。

3.1 文字列結合 (+ 演算子)

+ 演算子は特殊です。オペランドのいずれかが文字列である場合、JavaScriptはもう一方のオペランドも文字列に変換し、結合を行います。

let result1 = "5" + 2;
console.log(result1); // 出力: "52" (数値 2 が文字列 "2" に変換される)

let result2 = "5" + true;
console.log(result2); // 出力: "5true"

let result3 = "5" + null;
console.log(result3); // 出力: "5null"

3.2 算術演算子 (-, *, /, %)

+ 以外の算術演算子は、常にオペランドを数値に変換しようとします。

let result4 = "5" - 2;
console.log(result4); // 出力: 3 (文字列 "5" が数値 5 に変換される)

let result5 = "10" * "2";
console.log(result5); // 出力: 20

let result6 = "hello" - 2;
console.log(result6); // 出力: NaN ("hello" は数値に変換できない)

let result7 = true + 1;
console.log(result7); // 出力: 2 (true が 1 に変換される)

3.3 比較演算子 (== vs ===)

  • == (緩い比較): 比較の前に型強制を実行します。
  • === (厳密な比較): 型強制を実行しません。型が異なる場合は即座に false を返します。
// 緩い比較 (==) - 型強制が発生
console.log(5 == "5");   // 出力: true
console.log(true == 1);  // 出力: true
console.log(null == undefined); // 出力: true (特殊な例)
console.log(0 == false); // 出力: true

// 厳密な比較 (===) - 使用を推奨
console.log(5 === "5");   // 出力: false
console.log(true === 1);  // 出力: false
console.log(null === undefined); // 出力: false

3.4 論理演算子 (&&, ||, !)

論理演算子は評価時に値をブーリアンに強制変換しますが、戻り値は元の値を保持します(! は除きます)。

// || (OR): 最初の Truthy な値を返すか、最後の値を返す
console.log("hello" || 0); // 出力: "hello"
console.log(0 || "world"); // 出力: "world"

// && (AND): 最初の Falsy な値を返すか、最後の値を返す
console.log("hello" && 0); // 出力: 0
console.log("hello" && "world"); // 出力: "world"

// ! (NOT): ブーリアン値を返す
console.log(!0); // 出力: true
console.log(!"hello"); // 出力: false

4. ベストプラクティス

  1. 厳密等価 (=== および !==) を使用する: 予期せぬ型強制によるバグを防ぐため、== の使用は避けましょう。
  2. 明示的な変換を優先する: 型を変換したいときは、Number(value) のように明示的に記述することで、コードの意図が明確になります。
  3. Falsy な値を把握する: false, 0, "", null, undefined, NaN を暗記しておくと、条件判断(if (value) など)を書く際に非常に役立ちます。
  4. ツールを活用する: ESLint などの静的解析ツールを使用して、潜在的な型強制の問題を事前にキャッチしましょう。