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)); // 出力: NaN2.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オブジェクトはこのメソッドを持っています。
注意: null や undefined に対してこのメソッドを呼び出すとエラーになります。
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(偽値)リスト:
false0(ゼロ)-0(マイナスゼロ)0n(BigInt ゼロ)""(空文字列)nullundefinedNaN
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); // 出力: false3.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"); // 出力: false4. ベストプラクティス
- 厳密等価 (
===および!==) を使用する: 予期せぬ型強制によるバグを防ぐため、==の使用は避けましょう。 - 明示的な変換を優先する: 型を変換したいときは、
Number(value)のように明示的に記述することで、コードの意図が明確になります。 - Falsy な値を把握する:
false,0,"",null,undefined,NaNを暗記しておくと、条件判断(if (value)など)を書く際に非常に役立ちます。 - ツールを活用する: ESLint などの静的解析ツールを使用して、潜在的な型強制の問題を事前にキャッチしましょう。