変数とデータ型(let, const, プリミティブ型)
2025-07-28はじめに
JavaScriptを学ぶ上で、変数とデータ型の理解は基礎中の基礎です。この知識なしでは効果的なプログラミングはできません。現代のJavaScript(ES6以降)で使用される変数宣言方法(letとconst)と、JavaScriptの基本的なデータ型について詳しく解説します。
変数宣言:letとconst
変数とは
変数はデータを一時的にしまっておく「箱」のようなものです。たとえば「点数」や「名前」など、プログラムの中であとから使いたい値を入れておくために使います。プログラム内でデータを保持したり、参照したりするために使用します。変数を使うと、同じ値を何度も書かずにすみ、プログラムがわかりやすくなります。
var, let, constの違い
ES6以前はvarのみでしたが、ES6でletとconstが導入されました。letは再代入が可能な変数を宣言するために使い、ブロックスコープ({}内の範囲)で有効です。再宣言はできませんが、値の変更は可能です。
一方、constは定数を宣言するために使われ、一度代入した値を変更できません。ただし、オブジェクトや配列をconstで宣言した場合、プロパティや要素の内容は変更できます。
これらを適切に使い分けることで、予期しない値の変更を防ぎ、安全で可読性の高いコードを書くことができます。
| 特徴 | var | let | const |
|---|---|---|---|
| 再宣言 | ○ | × | × |
| 再代入 | ○ | ○ | × |
| スコープ※ | 関数 | ブロック | ブロック |
| ホイスティング※ | ○ | △ | △ |
varは再宣言・再代入が可能で、同じ名前の変数をもう一度宣言してもエラーにならず、関数スコープ内でのみ有効です。また、「巻き上げ(ホイスティング)」という仕組みにより、変数宣言がスクリプトの先頭に自動的に移動してしまうため、意図しない動作を引き起こすことがあります。
※現代のJavaScriptではvarはほとんど使われず、letとconstが推奨されます。
※スコープとホイスティングについては後述
letの使用例
letは再代入が可能な変数を宣言するために使い、ブロックスコープ({}内の範囲)で有効です。再宣言はできませんが、値の変更は可能です。
let count = 10; // 変数宣言と初期化
count = 20; // 再代入可能
console.log(count); // 20
let message; // 宣言のみ(値はundefined)
message = "Hello";
console.log(message); // "Hello"
constの使用例
constは定数を宣言するために使われ、一度代入した値を変更できません。ただし、オブジェクトや配列をconstで宣言した場合、プロパティや要素の内容は変更できます。
const PI = 3.14159; // 宣言と初期化必須
// PI = 3.14; // エラー: 再代入不可
const user = { name: "太郎", age: 25 };
user.age = 26; // オブジェクトのプロパティは変更可能
// user = {}; // エラー: 再代入は不可
letとconstの使い分け
基本はconstを使用し、再代入が必要な場合のみletを使います。
これにより、意図しない再代入を防ぎ、コードの安全性が向上します。
データ型:プリミティブ型とオブジェクト型
JavaScriptのデータ型はプリミティブ型(基本型)とオブジェクト型に大別されます。

以下にプリミティブ型を列挙します。オブジェクト型は別ページにて解説します。
オブジェクト型について
プリミティブ型(基本型)
- 数値(Number):整数と浮動小数点数
let age = 25;
let price = 99.95;
- 文字列(String):テキストデータ
let name = "山田太郎";
let greeting = 'こんにちは';
- 真偽値(Boolean):true/false
let isActive = true;
let isCompleted = false;
- undefined:値が未定義
let x; // 自動的にundefined
- null:値が存在しないことを明示
let user = null;
- シンボル(Symbol):ES6で追加、一意な識別子
const id = Symbol("id");
- 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"
オブジェクト型は、複数の値を名前(キー)と値のペアでまとめて管理できるデータ型です。1つの箱に「プロパティ(名前: 値)」をいくつも入れられるイメージです。オブジェクト型は別途説明します。
オブジェクト型について
変数のスコープ
変数のスコープとは、「その変数が使える範囲」のことです。次の種類のスコープがJavascriptでは用意されています。スコープが狭い方が、思わぬバグを防げるポイントがあります。

グローバルスコープ
- プログラム全体からアクセスできる
- 例:関数やブロックの外で宣言した変数
関数スコープ
- 関数の中だけで使える
varで宣言するとこのスコープになる
ブロックスコープ
{}の中だけで使えるletやconstはこれになる(ifやforの中だけなど)
letとconstはブロックスコープ({}で囲まれた範囲)を持ちます。波かっこ {} の内部で宣言された変数や定数は、そのブロックの中でのみ有効です。localVarとLOCAL_CONSTはブロック内では正常に参照できますが、ブロック外からアクセスしようとするとスコープ外エラーが発生します。これにより、変数の誤使用や衝突を防ぐことができます。
{
let localVar = "内部";
const LOCAL_CONST = "定数";
console.log(localVar); // "内部"
console.log(LOCAL_CONST); // "定数"
}
// console.log(localVar); // エラー
// console.log(LOCAL_CONST); // エラー
スコープのチェーン
JavaScriptは変数を探す際に、現在のスコープから外側のスコープへと順に探します。globalは関数の外で宣言されているため、どこからでもアクセスできます。一方、localは関数checkScopeの中で宣言されており、その関数の中でしか使えません。関数内では両方の変数を参照できますが、関数の外からlocalにアクセスしようとするとエラーになります。これにより、関数ごとに独立した変数管理が可能になります。
let global = "グローバル";
function checkScope() {
let local = "ローカル";
console.log(local); // "ローカル"
console.log(global); // "グローバル"
}
checkScope();
console.log(global); // "グローバル"
// console.log(local); // エラー
変数の命名規則
JavaScriptの変数名(識別子)のルール
変数名には文字・数字・アンダースコア(_)・ドル記号($)が使えますが、数字で始めることはできません。
- 使用可能な文字: 文字、数字、_、$
- 数字で始められない
- 予約語は使用不可
- 大文字小文字を区別
- 意味のある名前を付ける(推奨で絶対条件ではない)
- 定数は大文字で(慣例)
また、ifやforなどの予約語は使用不可で、大文字と小文字は区別されます。可読性を高めるために、意味のある名前を付けることが推奨され、定数は慣例的にすべて大文字で書かれます。
スコープについては別記事にて詳細に説明しています。Javascriptのスコープ
命名規則
Javascriptの命名規約の一般的な例です。
| 記法 | 記法名 | 例 |
|---|---|---|
| コンポーネント名 | アッパーキャメルケース | UserForm |
| 変数名 | ローワーキャメルケース | sampleFunction |
| 定数名 | スネークケース | API_URL |
| メソッド名 | ローワーキャメルケース | addNumber |
| プロパティ名 | ローワーキャメルケース | userName |
| クラス名 | アッパーキャメルケース | MyCar |
基本ルール(文法的制約)にて使える文字は以下のものになり、それを守れば問題ありません。
使える文字
- 英字(A~Z, a~z)、数字(0~9)、アンダースコア
_、ドル記号$ - 先頭は数字にできない
大文字・小文字を区別
appleとAppleは別の変数
予約語は使えない
- 例:
if,for,let,returnなど
// 良い例
let userName = "太郎";
let あいう = 5;
const MAX_SIZE = 100;
// 悪い例
let 123abc = "test"; // 数字開始
let let = "reserved"; // 予約語
上の「良い例」では、userNameやあいう、MAX_SIZEのようにルールに沿った命名がされています。letやconstで宣言され、数字で始まらず、予約語も使用していません。
一方「悪い例」では、123abcのように数字で始まる名前や、letのような予約語を変数名に使っており、どちらも文法エラーになります。命名規則を守ることで、エラーを防ぎ可読性を高めることができます。
ホイスティング
変数や関数の定義をコードが実行される前にメモリに配置する挙動のことを指します。その挙動から「宣言の巻き上げ」とも言われます。
関数のホイスティング
次のコードは、関数宣言の巻き上げ(ホイスティング)を示す例です。
f()の呼び出しが関数の定義より前に書かれていますが、JavaScriptでは関数宣言がスクリプトの先頭に自動的に「巻き上げ」られるため、エラーにならず正常に実行されます。その結果、console.log("Hoisting Test")が実行され、コンソールには「Hoisting Test」と表示されます。
f(); //f関数を実行
function f(){
console.log("Hoisting Test"); // Hoisting Test
}
一見すると実行文が関数の定義より前にあり、エラーになりそうですが問題なく動作しています。これはホイスティングによってコードが実行される前に関数の定義がメモリに配置されているため、実行することができています。
varを使った場合
varで宣言された変数は、スクリプトの実行前に宣言だけが自動的に先頭へ移動します。
console.log(x); // undefined
var x = 0; // 変数xの宣言
今度は変数xの宣言よりも前にconsole.logでxの値を取得しています。こちらも一見エラーになりそうですが、undefinedが出力されます。
変数も関数同様、ホイスティングによってコード実行前に変数xのメモリを確保しているので、console.logで問題なく参照することができています。注意点としては、行っているのはメモリの確保のみで、値は代入されていないので中身はundefined(未定義)となります。
undefinedは値が未定義の場合に自動で代入されるキーワードになります。事前に変数xのメモリ確保とundefinedの代入を行ってからコードを実行できます。
var変数ではこういった処理がコード実行前に行われるため、エラーが発生することなく変数の値を出力することができます。letやconstでは同じ書き方をするとエラーになる点が異なります。
let、const場合
letやconstも内部的にはホイスティングされますが、**「初期化前の一時的デッドゾーン(TDZ)」**が存在するため、宣言より前にアクセスするとReferenceErrorが発生します。
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 という値で初期化されます。つまり、varと違って宣言前に使うことはできません。安全で予測しやすいコードを書くための仕組みです。
テンプレートリテラル
ES6で導入された文字列表現で、変数を埋め込んだり複数行の文字列を簡単に書けます。JavaScriptのテンプレートリテラルは、文字列をもっと便利に書ける方法です。バッククォート( ` )で囲むのが特徴で、次のようなメリットがあります。リテラルについて
- 変数や式を埋め込める
${...} の中に変数や計算式を書けます。
const name = "太郎";
console.log(`こんにちは、${name}さん!`); // こんにちは、太郎さん!
- 複数行の文字列をそのまま書ける。
改行もエスケープなしでOK。
const text = `1行目 2行目`;
- 式の結果も入れられる。
console.log(`2 + 3 = ${2 + 3}`); // 2 + 3 = 5
テンプレートリテラルのポイント
- 文字列を扱うときに
" "や' 'の代わりに **`** を使う ${}で変数や式を直接書けるので、+で文字列をつなぐ必要が減る
const name = "太郎";
const age = 25;
// 従来の方法
console.log("名前: " + name + ", 年齢: " + age);
// テンプレートリテラル
console.log(`名前: ${name}, 年齢: ${age}`);
// 複数行
const message = `
こんにちは、${name}さん。
あなたの年齢は${age}歳ですね。
`;
まとめ
JavaScript学習で変数やデータ型を理解することは、プログラムの土台を作るために必須です。変数は値を入れて名前で呼び出すための入れ物、データ型はその値の種類や使い方のルールを決めます。
これを理解していないと、値を正しく扱えず、計算や条件分岐、データ保存などの処理で思わぬエラーが起きます。
演習問題
初級問題(3問)
- 以下のコードの出力結果は?
let x = 10;
x = 20;
const y = x + 5;
console.log(y);
- 正しい変数名をすべて選びなさい。
- a)
let 1stPlace; - b)
let user_name; - c)
let const; - d)
let $price; - e)
let first-name; - f)
let レモン;
- 次のコードをテンプレートリテラルを使って書き換えなさい。
const product = "りんご";
const price = 150;
console.log(product + "の価格は" + price + "円です");
中級問題(6問)
- 以下のコードの出力結果とその理由を説明しなさい。
console.log(typeof null);
console.log(typeof undefined);
console.log(typeof {});
console.log(typeof []);
- 次のコードの間違いを指摘し、修正しなさい。
const PI;
PI = 3.14159;
- スコープに関する次のコードの出力結果は?
let a = 1;
{
let a = 2;
console.log(a);
}
console.log(a);
- 次のコードの出力結果を答えなさい。
const obj = { prop: "value" };
obj.prop = "new value";
console.log(obj.prop);
obj = { newProp: "test" };
- 以下のコードを実行した場合の
xの値は?
let x = "10";
x = x + 5;
x = x - 2;
- 次の2つのコードの違いを説明しなさい。
// コード1
let a = b = 10;
// コード2
let c = 10;
let d = 10;
上級問題(3問)
- 次のコードの出力結果とその理由を説明しなさい。
function test() { console.log(a);
console.log(b);
var a = 1;
let b = 2;
}
test();
- 以下のコードの出力結果を順に答えなさい。
let x = 10;
{
console.log(x);
let x = 20;
console.log(x);
}
console.log(x);
- 次のようなユーザー情報を表すオブジェクトをコピーしてください。
このオブジェクトをコピーして新しいオブジェクトを作成し、address.prefectureを”大阪府”に変更するコードを書きなさい。ただし、元のuserオブジェクトは変更されないようにしなさい。
javascript const user = {
name: "山田太郎",
age: 30,
address: {
postalCode: "100-0001",
prefecture: "東京都"
}
};
解答例
初級問題解答
- コードの出力結果
(xが20に更新され、yは20 + 5で25になる)
let x = 10;
x = 20;
const y = x + 5;
console.log(y); // Output: 25
- 正しい変数名
- b)
user_name - d)
$price - f) レモン;
- テンプレートリテラル版
console.log(`${product}の価格は${price}円です`);
中級問題解答
- コードの出力結果とその理由
console.log(typeof null); // object (歴史的経緯)
console.log(typeof undefined); // undefined
console.log(typeof {}); // object
console.log(typeof []); // object (配列もオブジェクトの一種)
- 次のコードの間違い
間違い: constは宣言と同時に初期化が必要。
修正例:
const PI = 3.14159;
- スコープに関する次のコードの出力結果
let a = 1;
{
let a = 2;
console.log(a); // 2
}
console.log(a); // 1
ブロックスコープの内側と外側で別々の変数(a)として認識されている。
- コードの出力結果
"new value"まで表示された後、objへの再代入でエラーとなる。
const obj = { prop: "value" };
obj.prop = "new value";
console.log(obj.prop); // new valueが表示される
obj = { newProp: "test" }; // 再代入しているのでエラー
- コードを実行した場合の
xの値
let x = "10"; // x = "10"
x = x + 5; // x = "105"
x = x - 2; // x = 103
- 2つのコードの違い
コード1: bは暗黙的にグローバル変数になる
理由は宣言を省略して定義した変数は全て、グローバル変数として見做されるから
コード2: cとdは別々の変数
上級問題解答
- コードの出力結果とその理由
// 表示結果
undefined
Uncaught ReferenceError ReferenceError: Cannot access 'b' before initialization
a: undefined (varはホイスティングされる)
b: エラー (letはホイスティングされるがTDZ(Temporal Dead Zone) にある)
- コードの出力結果
(エラーで実行中断)
Uncaught ReferenceError ReferenceError: Cannot access 'x' before initialization
- オブジェクトをコピーして新しいオブジェクトを作成
オブジェクト型変数をコピーする場合はディープコピーして新しいオブジェクトを作成します
javascript const newUser = {
...user,
address: {
...user.address,
prefecture: "大阪府"
}
};