目次
概要
JavaScriptにおけるデータ型は、大きく分けて「プリミティブ型」と「オブジェクト型」の2種類に分類されます。これらはメモリ上での扱いやデータの不変性において根本的に異なる性質を持っており、予期せぬバグを防ぐためにはそれぞれの挙動を正しく把握することが不可欠です。本記事では、各データ型の定義と具体的な利用シーンについて解説します。
仕様(入出力)
データ型の分類と意味
| データ型 | 意味 |
| プリミティブ型 | 値そのものが変数に直接格納される、不変(イミュータブル)な基本データです。 |
| オブジェクト型 | 複数の値や関数をひとまとめにしたデータ構造で、プリミティブ型以外のすべてを指します。 |
プリミティブ型の詳細
| プリミティブ型 | 意味 | データ例 |
| Boolean | 真偽値(論理値)を表します。 | true, false |
| String | テキスト(文字列)データを表します。 | "mori", 'Tokyo' |
| Number | 整数および浮動小数点数を表します。 | 1024, 3.14 |
| undefined | 変数が宣言されたが値が代入されていない状態を表します。 | undefined |
| Null | 値が「空」であることを意図的に表します。 | null |
| Symbol | 一意で不変な識別子を作成します。 | Symbol('key') |
基本の使い方
プリミティブ型は単一の値を保持する際に使用し、オブジェクト型(配列や連想配列)は関連する複数のデータを構造化して管理する際に使用します。特にオブジェクト型は、その内部の値を後から書き換えることが可能であるという動的な性質を持ちます。
コード全文(HTML / JAVASCRIPT)
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Smart Home Sensor Dashboard</title>
</head>
<body>
<div id="sensor-dashboard">
<h2>センサーネットワーク監視</h2>
<div id="display-output"></div>
<hr>
<button id="check-types-btn">データ型を解析する</button>
</div>
<script type="module" src="main.js"></script>
</body>
</html>
JavaScript
/**
* センサーデバイスの状態を管理するスクリプト
* シナリオ:IoTデバイスからのデータ受信
*/
// 1. プリミティブ型の定義
const deviceId = 5050; // Number
const deviceOwner = "mori"; // String
const isActive = true; // Boolean
const lastError = null; // Null
let pendingCommand; // undefined
// 2. オブジェクト型の定義(基本のオブジェクト)
const hardwareInfo = {
model: "NX-200",
revision: 1.2
};
// 3. オブジェクト型の定義(配列)
const signalStrengthHistory = [85, 82, 90];
// 4. オブジェクト型の定義(配列内のオブジェクト)
const logEntries = [
{ timestamp: "10:00", value: 24.5, reporter: "mori" },
{ timestamp: "10:05", value: 24.6, reporter: "system" }
];
const output = document.getElementById('display-output');
/**
* 各変数のデータ型をコンソールと画面に出力する
*/
const analyzeDataTypes = () => {
const dataList = [
{ name: "deviceId", val: deviceId },
{ name: "deviceOwner", val: deviceOwner },
{ name: "isActive", val: isActive },
{ name: "lastError", val: lastError },
{ name: "pendingCommand", val: pendingCommand },
{ name: "hardwareInfo", val: hardwareInfo },
{ name: "signalStrengthHistory", val: signalStrengthHistory },
{ name: "logEntries", val: logEntries }
];
output.innerHTML = "";
dataList.forEach(item => {
const type = typeof item.val;
const info = `${item.name}: 型 = ${type}`;
console.log(info, item.val);
const p = document.createElement('p');
p.textContent = info;
output.appendChild(p);
});
};
document.getElementById('check-types-btn').addEventListener('click', analyzeDataTypes);
カスタムポイント
typeof演算子を使用して、動的に受け取ったデータが期待する型(例えばNumberかどうか)であるかを判定するガード節を導入してください。- 文字列(
String)を扱う際は、テンプレートリテラル(バッククォート)を使用して変数を埋め込む形式に変更することで、可読性を高めることができます。
注意点
typeof nullを実行すると歴史的な経緯により"object"が返されます。値が本当にオブジェクトであるかを確認する場合は、nullでないことも同時にチェックする必要があります。- プリミティブ型は不変であるため、一度作成した値自体を書き換えることはできません(変数への再代入は可能)。一方、オブジェクト型は定数(
const)で宣言しても内部のプロパティは変更可能です。 - 配列も
typeofでは"object"と判定されます。配列かどうかを厳密に判定するにはArray.isArray()メソッドを使用してください。
応用
Symbol 型を使用して、オブジェクトに隠蔽性の高い一意のキーを設定する例です。
/**
* 内部管理用のユニークIDをSymbolで定義
*/
const internalId = Symbol('id');
const userProfile = {
[internalId]: "SECRET_999",
userName: "mori"
};
// 通常のループや JSON.stringify では internalId は露出しない
console.log(Object.keys(userProfile)); // ["userName"]
console.log(userProfile[internalId]); // "SECRET_999"
まとめ
JavaScriptのデータ型を理解することは、メモリ管理や意図しないデータの書き換えを防ぐための第一歩です。数値や文字列といったシンプルなプリミティブ型と、配列や連想配列のように複雑な構造を持つオブジェクト型では、代入時の挙動やプロパティの有無が大きく異なります。プログラム内でデータを扱う際は、その値がどちらの型に属しているかを常に意識し、適切な判定メソッドを用いることで、堅牢でメンテナンス性の高いコードを構築することが可能になります。特に大規模なデータを扱うシナリオでは、オブジェクト型のネスト構造を正確に定義し、型に基づいた処理の分岐を行うことが推奨されます。
