変数とデータ型(let, const, プリミティブ型)

2025-07-28

はじめに

JavaScriptを学ぶ上で、変数とデータ型の理解は基礎中の基礎です。この知識なしでは効果的なプログラミングはできません。本記事では、現代のJavaScript(ES6以降)で使用される変数宣言方法(letconst)と、JavaScriptの基本的なデータ型について詳しく解説します。最後には理解度を確認するための演習問題を用意しています。

変数宣言:letとconst

変数とは

変数はデータを格納するための「名前付きの容器」です。プログラム内でデータを保持したり、参照したりするために使用します。

var, let, constの違い

ES6以前はvarのみでしたが、ES6でletconstが導入されました。

特徴varletconst
再宣言××
再代入×
スコープ※関数ブロックブロック
ホイスティング※

現代のJavaScriptではvarはほとんど使われず、letconstが推奨されます。

※スコープとホイスティングについては後述

letの使用例

let count = 10; // 変数宣言と初期化
count = 20;    // 再代入可能
console.log(count); // 20

let message;   // 宣言のみ(値はundefined)
message = "Hello";
console.log(message); // "Hello"

constの使用例

const PI = 3.14159; // 宣言と初期化必須
// PI = 3.14;      // エラー: 再代入不可

const user = { name: "太郎", age: 25 };
user.age = 26;     // オブジェクトのプロパティは変更可能
// user = {};      // エラー: 再代入は不可

letとconstの使い分け

基本はconstを使用し、再代入が必要な場合のみletを使います。これにより、意図しない再代入を防ぎ、コードの安全性が向上します。

データ型:プリミティブ型とオブジェクト

JavaScriptのデータ型はプリミティブ型(基本型)とオブジェクト型に大別されます。

プリミティブ型(基本型)

  1. 数値(Number): 整数と浮動小数点数
   let age = 25;
   let price = 99.95;
  1. 文字列(String): テキストデータ
   let name = "山田太郎";
   let greeting = 'こんにちは';
  1. 真偽値(Boolean): true/false
   let isActive = true;
   let isCompleted = false;
  1. undefined: 値が未定義
   let x; // 自動的にundefined
  1. null: 値が存在しないことを明示
   let user = null;
  1. シンボル(Symbol): ES6で追加、一意な識別子
   const id = Symbol("id");
  1. BigInt: ES2020で追加、大きな整数
   const bigNum = 1234567890123456789012345678901234567890n;

型の確認方法

typeof演算子でデータ型を確認できます。

console.log(typeof 42);        // "number"
console.log(typeof "text");    // "string"
console.log(typeof true);      // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null);      // "object" (歴史的な理由)
console.log(typeof Symbol());  // "symbol"
console.log(typeof 10n);       // "bigint"

変数のスコープ

ブロックスコープ

letconstはブロックスコープ({}で囲まれた範囲)を持ちます。

{
  let localVar = "内部";
  const LOCAL_CONST = "定数";
  console.log(localVar);    // "内部"
  console.log(LOCAL_CONST); // "定数"
}
// console.log(localVar);   // エラー
// console.log(LOCAL_CONST); // エラー

スコープのチェーン

JavaScriptは変数を探す際に、現在のスコープから外側のスコープへと順に探します。

let global = "グローバル";

function checkScope() {
  let local = "ローカル";
  console.log(local);   // "ローカル"
  console.log(global); // "グローバル"
}

checkScope();
console.log(global);   // "グローバル"
// console.log(local); // エラー
  1. 使用可能な文字: 文字、数字、_、$
  2. 数字で始められない
  3. 予約語は使用不可
  4. 大文字小文字を区別
  5. 意味のある名前を付ける(推奨で絶対条件ではない)
  6. 定数は大文字で(慣例)

変数の命名規則

// 良い例
let userName = "太郎";
let あいう = 5;
const MAX_SIZE = 100;

// 悪い例
let 123abc = "test"; // 数字開始
let let = "reserved"; // 予約語

ホイスティング

変数や関数の定義をコードが実行される前にメモリに配置する挙動のことを指します。
その挙動から「宣言の巻き上げ」とも言われます。

関数のホイスティング

f(); //f関数を実行

function f(){
    console.log("Hoisting Test"); // Hoisting Test
}

一見すると実行文が関数の定義より前にあり、エラーになりそうですが問題なく動作しています。これはホイスティングによってコードが実行される前に関数の定義がメモリに配置されているため、実行することができています。

varを使った場合

console.log(x); // undefined

var x = 0; // 変数xの宣言

今度は変数xの宣言よりも前にconsole.logでxの値を取得しています。
こちらも一見エラーになりそうですが、undefinedが出力されます。

変数も関数同様、ホイスティングによってコード実行前に変数xのメモリを確保しているので、console.logで問題なく参照することができています。

注意点としては、行っているのはメモリの確保のみで、値は代入されていないので中身はundefined(未定義)となります。undefinedは値が未定義の場合に自動で代入されるキーワードになります。

事前に変数xのメモリ確保とundefinedの代入を行ってからコードを実行できます。var変数ではこういった処理がコード実行前に行われるため、エラーが発生することなく変数の値を出力することができます。

let、const場合

console.log(x); // ReferenceError
let x = 0;

console.log(x); // ReferenceError
const x = 0;

let、const変数の場合は、
[Uncaught ReferenceError: Cannot access ‘x’ before initialization]
というエラーメッセージが表示されます。let、constの場合は初期化されるまではTDZ(Temporal Dead Zone) にあるとみなされるため、エラーが起きます。TDZとは「一時的なデッドゾーン」と言います。TDZ の中にいる間は、変数は値で初期化されておらず、何かアクセスしようとすると ReferenceError が発生することになります。変数は、宣言されたコードの行まで実行されると、値で初期化されます。変数宣言で初期値を指定しなかった場合は、 undefined という値で初期化されます。

テンプレートリテラル

ES6で導入された文字列表現で、変数を埋め込んだり複数行の文字列を簡単に書けます。

const name = "太郎";
const age = 25;

// 従来の方法
console.log("名前: " + name + ", 年齢: " + age);

// テンプレートリテラル
console.log(`名前: ${name}, 年齢: ${age}`);

// 複数行
const message = `
  こんにちは、${name}さん。
  あなたの年齢は${age}歳ですね。
`;

演習問題

初級問題(3問)

  1. 以下のコードの出力結果は?
   let x = 10;
   x = 20;
   const y = x + 5;
   console.log(y);
  1. 正しい変数名をすべて選びなさい。
  • a) let 1stPlace;
  • b) let user_name;
  • c) let const;
  • d) let $price;
  • e) let first-name;
  • f) let レモン;
  1. 次のコードをテンプレートリテラルを使って書き換えなさい。
   const product = "りんご";
   const price = 150;
   console.log(product + "の価格は" + price + "円です");

中級問題(6問)

  1. 以下のコードの出力結果とその理由を説明しなさい。
   console.log(typeof null);
   console.log(typeof undefined);
   console.log(typeof {});
   console.log(typeof []);
  1. 次のコードの間違いを指摘し、修正しなさい。
   const PI;
   PI = 3.14159;
  1. スコープに関する次のコードの出力結果は?
   let a = 1;
   {
     let a = 2;
     console.log(a);
   }
   console.log(a);
  1. 次のコードの出力結果を答えなさい。
   const obj = { prop: "value" };
   obj.prop = "new value";
   console.log(obj.prop);
   obj = { newProp: "test" };
  1. 以下のコードを実行した場合のxの値は?
   let x = "10";
   x = x + 5;
   x = x - 2;
  1. 次の2つのコードの違いを説明しなさい。
   // コード1
   let a = b = 10;

   // コード2
   let c = 10;
   let d = 10;

上級問題(3問)

  1. 次のコードの出力結果とその理由を説明しなさい。
function test() {   console.log(a);
   console.log(b);
   var a = 1;
   let b = 2;
}
test();
  1. 以下のコードの出力結果を順に答えなさい。
let x = 10;
{ 
    console.log(x); 
    let x = 20; 
    console.log(x); 
} 
console.log(x);
  1. 次のようなユーザー情報を表すオブジェクトをコピーしてください。

このオブジェクトをコピーして新しいオブジェクトを作成し、address.prefectureを”大阪府”に変更するコードを書きなさい。ただし、元のuserオブジェクトは変更されないようにしなさい。

javascript const user = {
   name: "山田太郎",
   age: 30,
   address: { 
       postalCode: "100-0001", 
       prefecture: "東京都" 
   }
};

解答例

初級問題解答

  1. コードの出力結果
    (xが20に更新され、yは20 + 5で25になる)
      let x = 10;
   x = 20;
   const y = x + 5;
   console.log(y);  // Output: 25
  1. 正しい変数名
  • b) user_name  
  • d) $price
  • f) レモン;
  1. テンプレートリテラル版
   console.log(`${product}の価格は${price}円です`);

中級問題解答

  1. コードの出力結果とその理由
    console.log(typeof null);   // object (歴史的経緯)
    console.log(typeof undefined); // undefined
    console.log(typeof {}); // object
    console.log(typeof []); // object (配列もオブジェクトの一種)
  1. 次のコードの間違い

間違い: constは宣言と同時に初期化が必要。
修正例:

   const PI = 3.14159;
  1. スコープに関する次のコードの出力結果
   let a = 1;
   {
     let a = 2;
     console.log(a);  // 2
   }
   console.log(a);  // 1

ブロックスコープの内側と外側で別々の変数(a)として認識されている。

  1. コードの出力結果

"new value"まで表示された後、objへの再代入でエラーとなる。

    const obj = { prop: "value" };
    obj.prop = "new value";
    console.log(obj.prop);  // new valueが表示される
    obj = { newProp: "test" };  // 再代入しているのでエラー
  1. コードを実行した場合のxの値
   let x = "10";   // x = "10"
   x = x + 5;   // x = "105"
   x = x - 2;   // x = 103
  1. 2つのコードの違い

コード1: bは暗黙的にグローバル変数になる
 理由は宣言を省略して定義した変数は全て、グローバル変数として見做されるから

コード2: cdは別々の変数

上級問題解答

  1. コードの出力結果とその理由
// 表示結果
undefined

Uncaught ReferenceError ReferenceError: Cannot access 'b' before initialization

a: undefined (varはホイスティングされる)

b: エラー (letはホイスティングされるがTDZ(Temporal Dead Zone) にある)

  1. コードの出力結果

(エラーで実行中断)

Uncaught ReferenceError ReferenceError: Cannot access 'x' before initialization
  1. オブジェクトをコピーして新しいオブジェクトを作成

オブジェクト型変数をコピーする場合はディープコピーして新しいオブジェクトを作成します

javascript const newUser = { 
    ...user, 
    address: { 
        ...user.address, 
        prefecture: "大阪府" 
    } 
};