1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptの「巻き上げ(hoisting)」とは? var・let・constの違いを整理して理解する

Last updated at Posted at 2025-10-20

はじめに

JavaScriptのコードを読んでいて、

varletconstってどうちがうんだっけ?」
「関数が定義される前に使われているのに、なぜか動く……?」

と感じたことはありませんか?

この記事では、これらの宣言子の違いと、JavaScript特有の「巻き上げ(hoisting)」という仕組みを整理して理解します。
これを押さえることで、変数宣言まわりのミスを減らし、コードの挙動をしっかり納得できるようになります。

この記事の内容

  • var / let / const の違い
  • 「巻き上げ(hoisting)」とは何か
  • 各宣言子での具体的な動作の違い
  • 各宣言子の使い分けの目安
  • 実務で let / const が推奨される理由

var, let, const とは

varletconstは、JavaScriptで変数を宣言するためのキーワードです。
JavaScriptの仕様はECMAScriptという標準仕様で定められており、ECMAScript 5(2009年)まではvarしか存在しませんでした。
letconstECMAScript 6(2015年)で導入され、より安全で直感的な変数管理が可能になりました。

各キーワードの違い早見表

キーワード 再宣言 再代入 巻き上げ
var
let × ×
const × × ×

この表からわかるように、varは柔軟(=危険)で、letconstは意図しない再宣言や再代入を防ぐ仕組みになっています。

巻き上げ(Hoisting)とは?

巻き上げ(hoisting)とは、変数や関数の宣言がスコープの先頭に移動したかのように扱われる仕組みのことです。
つまり、プログラムの途中で宣言しても、実際には最初に宣言されたように振る舞うということです。

var による巻き上げの例

console.log(x);
var x = 1;
console.log(x);

一見すると、最初のconsole.log(x)は未定義の変数を参照しているのでエラーになりそうですが、実際には次のように動作します。

var x;             // 巻き上げにより先頭で宣言された扱い
console.log(x);    // undefined
x = 1;
console.log(x);    // 1

var宣言の場合、変数の宣言部分のみが巻き上げられ、初期化はそのままの位置で行われます。

let / const の場合

console.log(y); // ReferenceError
let y = 10;
console.log(z); // ReferenceError
const z = 100;

letやconstも内部的にはスコープの先頭で「予約」されますが、初期化されるまではアクセスできません。この期間を Temporal Dead Zone(TDZ) と呼びます。

関数の巻き上げ

関数宣言も巻き上げの対象になります。そのため、定義より前で呼び出しても動作します。

console.log(square(3)); // OK
function square(x) { return x * x; }

ただし、関数式(変数に関数を代入する形)では挙動が異なります。

console.log(square(3)); // TypeError
var square = function(x) { return x*x; };

ここではvarの巻き上げが起きていますが、代入は後なので、squareは呼び出し時点ではundefinedになっています。

再宣言と再代入

再宣言の違い

var x = 1;
var x = 2; // OK

let y = 10;
let y; // SyntaxError: Identifier 'y' has already been declared

const z = 100;
const z; // SyntaxError: Identifier 'z' has already been declared

letconstでは同一スコープ内での再宣言は禁止です。

constの初期化

const a; // SyntaxError: Missing initializer in const declaration

constでは宣言と同時に初期化を行う必要があります。

再代入の違い

var x = 1;
x = 2; // OK

let y = 10;
y = 20; // OK

const z = 100;
z = 200; // TypeError: Assignment to constant variable.

constは再代入ができません。

const の制限とよくある誤解

constで宣言された変数は再代入ができないだけであり、中身(オブジェクトや配列の要素)は変更可能です。

const c = {x:1, y:2};
c.x = 10;
console.log(c) // {x: 10, y: 2}

constが「不変(immutable)」なのは参照自体であって、
その中身まで固定されるわけではありません。

使い分けの目安

  • var
    古いコードとの互換性目的で使われることが多い
    巻き上げにより、意図せず上書きされるリスクが高い
    現代のコードでは原則として使用しない

  • let
    ブロックスコープ内でのみ有効
    再宣言不可・再代入可
    一般的な変数に適する

  • const
    再代入不可
    定数や変更されない参照に使用するのが基本

letとconstを使うことで、varの持つ以下の問題を防げます。

  • 巻き上げによる予期せぬ値の参照
  • スコープの混乱
  • 意図しない上書き・再宣言

また、変数がどこで変更されうるかが明確になるため、バグの発見もしやすくなります(可読性と保守性が向上)。
constを基本に使い、再代入が必要な場合のみletを使うという方針が最近では一般的です。

まとめ

var、let、constはいずれも変数宣言に使うが、挙動が異なる
varには巻き上げ(hoisting)があり、宣言前に変数が使えてしまう
letとconstにはTDZ(Temporal Dead Zone)があり、宣言前アクセスでエラーになる
実務ではletとconstが推奨される
関数を宣言前に使えるのは巻き上げによるもの

参考文献

徹底マスターJavaScriptの教科書(2017) 磯博
https://developer.mozilla.org/ja/docs/Glossary/Hoisting

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?