JavaScript 入門

JavaScript データ型

他の多くのプログラミング言語と同様に、JavaScriptは異なる種類の値を分類し、処理するためにデータ型に依存しています。

この章では、JavaScriptにおける8つのデータ型を探索します。これには7つのプリミティブ型(Numbers, Strings, Booleans, Undefined, Null, BigInt, Symbol)と、1つの参照型(Object)が含まれます。

それぞれの特性、使用方法、そして複雑なプログラムを構築する上でなぜそれらが重要なのかを深く掘り下げていきましょう。

1. JavaScript における数値 (Numbers)

JavaScriptは、整数とフローティングポイント(浮動小数点数)を表すために Number 型を使用します。

他の言語とは異なり、JavaScriptには int(整数)や float(浮動小数点数)といった独立した型は存在しません。すべての数字は、IEEE 754 標準に従い、倍精度64ビット浮動小数点数として保存されます。

これは非常に広い範囲の数値を表現できることを意味しますが、非常に大きな数字や小さな数字を扱う際、あるいは複雑な計算を行う際の精度の問題には注意が必要です。

1.1 整数リテラル

整数リテラルは、異なる進数システムで表現できます:

  • 10進数 (Decimal): 最も一般的な表記法。例:10, 100, -5
  • 2進数 (Binary): 0b または 0B プレフィックスを使用。例:0b101(10進数の5)。
  • 8進数 (Octal): 0o または 0O プレフィックスを使用。例:0o12(10進数の10)。※厳格モード(Strict Mode)では一部制限があります。
  • 16進数 (Hexadecimal): 0x または 0X プレフィックスを使用。例:0x2A(10進数の42)。
let decimalNumber = 42;
let binaryNumber = 0b101010; // 42の2進数表示
let octalNumber = 0o52;    // 42の8進数表示
let hexadecimalNumber = 0x2A; // 42の16進数表示

console.log(decimalNumber);     // 出力: 42
console.log(binaryNumber);      // 出力: 42
console.log(octalNumber);       // 出力: 42
console.log(hexadecimalNumber);  // 出力: 42

1.2 浮点数リテラル

浮動小数点数は、小数部分を持つ数値を表します。これらは小数点のほか、科学的記数法(指数表記)でも記述できます。

let pi = 3.14159;
let scientificNotation = 1.23e5; // 1.23 * 10^5 = 123000 と同等

console.log(pi);                // 出力: 3.14159
console.log(scientificNotation); // 出力: 123000

1.3 特殊な数値

JavaScriptにはいくつかの特殊な数値が存在します:

  • NaN (Not a Number): 無効な数学的演算の結果を表します。
  • Infinity: JavaScriptで表現可能な上限を超えた正の数。
  • -Infinity: JavaScriptで表現可能な下限を超えた負の数。
let notANumber = 0 / 0;
let infinity = 1 / 0;
let negativeInfinity = -1 / 0;

console.log(notANumber);       // 出力: NaN
console.log(infinity);        // 出力: Infinity
console.log(negativeInfinity); // 出力: -Infinity

console.log(NaN === NaN); // 出力: false (NaNは自分自身とも等しくない)
console.log(Number.isNaN(notANumber)); // 出力: true (Number.isNaN() を使用してチェック)

       重要:NaN は自分自身と等しくないという特殊な性質を持っています。値が NaN かどうかをチェックするには、常に Number.isNaN() 関数を使用してください。

1.4 Number メソッド

Number オブジェクトは、数値を処理するための便利なメソッドを提供しています:

  • toFixed(digits): 定点表記法を使用して数値をフォーマットします(小数点以下の桁数を指定)。
  • toPrecision(precision): 指定された精度(有効数字の桁数)でフォーマットします。
  • parseInt(string, radix): 文字列を解析し、指定されたラジックス(基数)の整数を返します。
  • parseFloat(string): 文字列を解析し、浮動小数点数を返します。
let num = 3.14159;

console.log(num.toFixed(2));       // 出力: "3.14" (文字列を返す)
console.log(num.toPrecision(4));   // 出力: "3.142" (文字列を返す)
console.log(parseInt("10", 10));    // 出力: 10 (10進数として解析)
console.log(parseInt("0b101", 2)); // 出力: 5 (2進数として解析)
console.log(parseFloat("3.14"));   // 出力: 3.14

1.5 Number プロパティ

  • Number.MAX_VALUE: JavaScriptで表現可能な最大数値。
  • Number.MIN_VALUE: JavaScriptで表現可能な最小の正の数値(0に最も近い値)。
  • Number.POSITIVE_INFINITY: 正の無限大。
  • Number.NEGATIVE_INFINITY: 負の無限大。
  • Number.NaN: 「非数値」。

2. JavaScript における文字列 (Strings)

文字列はテキストデータを表すために使用されます。JavaScriptにおいて文字列はイミュータブル (Immutable) であり、一度作成されるとその値を変更することはできません。文字列を変更するように見える操作は、実際には新しい文字列を作成しています。

文字列はシングルクォート ('...')、ダブルクォート ("...")、またはバックティック (`...`) で囲むことができます。バックティックはテンプレートリテラルに使用されます。

let singleQuotedString = 'Hello, world!';
let doubleQuotedString = "これは文字列です。";
let backtickString = `これも文字列です。`;

console.log(singleQuotedString);   // 出力: Hello, world!
console.log(doubleQuotedString);   // 出力: これは文字列です。
console.log(backtickString);       // 出力: これも文字列です。

2.1 エスケープシーケンス

エスケープシーケンスは、直接入力しにくい特殊文字を文字列に含めるための記法です。

シーケンス表す文字
\'シングルクォート
\"ダブルクォート
\\バックスラッシュ(反斜線)
\n改行符 (New Line)
\rキャリッジリターン
\tタブ (Tab)
\bバックスペース
\fフォームフィード
let escapedString = "この文字列は \"ダブルクォート\" とバックスラッシュ \\ を含みます。";
let multiLineString = "この文字列は\n複数行にわたります。";

console.log(escapedString);   // 出力: この文字列は "ダブルクォート" とバックスラッシュ \ を含みます。
console.log(multiLineString);

2.2 文字列のプロパティとメソッド

  • length: 文字列の長さを返します。
  • charAt(index): 指定されたインデックス位置の文字を返します。
  • substring(start, end): 指定された範囲のサブ文字列を返します。
  • slice(start, end): substring と同様ですが、負のインデックスも受け付けます。
  • toUpperCase() / toLowerCase(): 大文字/小文字に変換します。
  • indexOf(value): 指定された値が最初に出現するインデックスを返します。
  • replace(searchValue, replaceValue): 最初に一致した箇所を置換します。
  • trim(): 両端の空白を削除します。
  • includes(searchString): 指定された文字列が含まれているかチェックします。
  • split(separator): 文字列を分割して配列にします。
let myString = "  Hello, World!  ";

console.log(myString.length);             // 出力: 17
console.log(myString.trim());             // 出力: "Hello, World!"
console.log(myString.includes("Hello"));  // 出力: true
console.log(myString.split(","));         // 出力: [ '  Hello', ' World!  ' ]

3. JavaScript におけるブーリアン (Booleans)

ブーリアン型は論理値を表します: true(真)または false(偽)。コードの意思決定の基礎であり、条件分岐や論理演算で使用されます。

3.1 ブーリアンリテラル

let isTrue = true;
let isFalse = false;

console.log(isTrue);    // 出力: true
console.log(isFalse);   // 出力: false

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

JavaScriptには「トゥルーシー (Truthy)」と「フォルシー (Falsy)」という概念があります。

  • Truthy: ブーリアンコンテキストで true と見なされる値。
  • Falsy: ブーリアンコンテキストで false と見なされる値。

以下の値は常に Falsy です:

  1. false
  2. 0 (ゼロ)
  3. -0 (マイナスゼロ)
  4. 0n (BigInt のゼロ)
  5. "" (空文字列)
  6. null
  7. undefined
  8. NaN

これら以外のすべての値(空のオブジェクト {} や配列 [] を含む)は Truthy です。

3.3 論理演算子

  • && (論理積 AND): 両方が true の場合に true を返す。
  • || (論理和 OR): 少なくとも一方が true の場合に true を返す。
  • ! (論理否定 NOT): ブーリアン値を反転させる。

4. アンディファインド (Undefined)

undefined 型は、undefined という一つの値のみを持ちます。これは、変数が宣言されたものの、まだ値が割り当てられていない状態を表します。JavaScriptエンジンによって自動的に割り当てられるデフォルト値です。

let unassignedVariable;
console.log(unassignedVariable); // 出力: undefined
console.log(typeof unassignedVariable); // 出力: "undefined"

5. ヌル (Null)

undefined とは異なり、null は明示的に代入される特殊なキーワードです。「値が存在しない」「空である」「未知である」ことを表します。開発者は通常、変数を空にしたり、現時点でオブジェクトを参照していないことを示すために null を代入します。

let emptyValue = null;
console.log(emptyValue); // 出力: null

       歴史的経緯:typeof null を実行すると、JavaScriptは "object" を返します。これは言語の初期から存在する有名なバグですが、互換性のために修正されていません。実際には null はオブジェクトではなくプリミティブ型です。

6. ビッグイント (BigInt)

BigInt は、任意の長さの整数を表現するための比較的新しいデータ型です。

標準の Number 型は、-(253 - 1) から 253 - 1 の範囲の整数しか安全に扱えません。これを超える巨大な整数(高精度なタイムスタンプや暗号演算など)が必要な場合に BigInt を使用します。末尾に n を付けるか、BigInt() 関数を呼び出して作成します。

const bigIntNum = 900719925474099123456789n;
console.log(typeof bigIntNum); // 出力: "bigint"

7. シンボル (Symbol)

Symbol は ES6 で導入されました。Symbol() 関数を呼び出すことで、一意(ユニーク)でイミュータブルな値を作成します。主にオブジェクトプロパティの衝突を防ぐためのキーとして利用されます。

let sym1 = Symbol("id");
let sym2 = Symbol("id");
console.log(sym1 === sym2); // 出力: false (記述が同じでも常にユニーク)

8. オブジェクト (Object) - 参照型

これまで紹介した7つの型は「プリミティブ型」であり、単一の値のみを保持します。対して Object(オブジェクト) は唯一の参照型(リファレンス型)であり、キーと値のペアの集合や、より複雑なデータ構造を保存できます。

参照型の核心的な特徴は、変数自体がデータそのものを保存するのではなく、メモリ内のヒープ(Heap)にある実際のデータへの「アドレス(参照)」を保存することにあります。

8.1 オブジェクトリテラル

let user = {
  name: "Alice",
  age: 28,
  greet: function() {
    console.log("Hello!");
  }
};
console.log(user.name); // 出力: Alice
user.greet();           // 出力: Hello!

8.2 配列 (Arrays)

配列は順序付けられたデータの集合です。typeof では "object" と返されますが、独自のメソッド(push, map など)を持ちます。

8.3 関数 (Functions)

JavaScriptにおいて関数は「第一級市民」です。つまり、関数も特殊なオブジェクトの一種です。変数に代入したり、他の関数に渡したりすることができます。

8.4 Map & Set(ES6 の新しいコレクション)

  • Map: Object と異なり、任意の型(オブジェクトや関数)をキーにできる強力なマップ構造。
  • Set: 重複を許さないユニークな値の集合。配列の重複除去などに便利です。

8.5 まとめ:なぜ「参照」を区別するのか?

参照型の理解において最も重要なのは代入操作です:

let objA = { count: 1 };
let objB = objA; // ここでコピーされるのは「アドレス」であり、オブジェクト本体ではない

objB.count = 2;
console.log(objA.count); // 出力: 2

プリミティブ型の場合、let a = 1; let b = a; と書くと b1 のコピーを受け取るため、b を変更しても a に影響は出ません。しかし参照型は、一度代入されると同じ実体を指すように「紐付け」られます。これは意図しないデータ書き換えの原因になりやすいため、開発において非常に重要な概念です。