なぜJavaScriptには「hoisting(巻き上げ)」という仕組みがあるのか?初心者エンジニアのための徹底解説

こんにちは。ゆうせいです。

JavaScriptを学んでいると、こんなふしぎな現象に出会ったことはありませんか?

console.log(message); // undefined
var message = "こんにちは";

「えっ、宣言より前に使えてるの!?なんでエラーじゃないの?」

そう思ったあなた、素晴らしい観察力です。この仕組みは 「hoisting(ホイスティング)」 と呼ばれるJavaScript独特の特徴なんです。

では、なぜJavaScriptはこんなややこしい仕組みを持っているのでしょうか?一緒に見ていきましょう。


Hoistingとは何か?

まず用語の意味からしっかり押さえましょう。

hoisting(ホイスティング)とは:
「変数や関数の宣言が、スコープの先頭に“持ち上げられる”ように振る舞う仕組み」です。

“hoist”は英語で「持ち上げる」という意味なので、「巻き上げ」と訳されることもあります。

つまり、コード上では下に書いていても、JavaScriptの解釈のときに上に移動して扱われるというわけです。


実際のコードで見てみよう

変数のhoisting(varの場合)

console.log(a); // undefined
var a = 5;

これは、JavaScript内部で以下のように処理されていると考えられます:

var a;
console.log(a); // undefined
a = 5;

つまり「宣言だけ」が巻き上げられて、代入はそのまま下に残っているという状態です。


関数のhoisting(関数宣言の場合)

greet(); // 呼び出し可能!

function greet() {
  console.log('こんにちは');
}

関数もhoistingされますが、関数宣言はまるごと(本体ごと)巻き上げられるため、呼び出し可能です。

// JavaScript内部のイメージ
function greet() {
  console.log('こんにちは');
}
greet(); // 呼び出しOK


なぜhoistingがあるのか?―設計上の理由

1. JavaScriptの仕様(インタプリタ型言語)

JavaScriptは「インタプリタ型」といって、コードを1行ずつ上から順にその場で実行する言語です。

ただし、実行に入る前に「準備(解析)」段階があります。この段階で、変数や関数の宣言が最初に処理されるように設計されているため、結果的に「巻き上がって見える」わけです。

これがhoistingの正体です。


2. 柔軟で寛容な記述を可能にするため

もともとJavaScriptは、HTMLに埋め込んで「ちょこっと動作を追加するための軽量な言語」として作られました。

そのため、以下のような「人間っぽいミス」や「順番違い」も許容してくれる設計思想だったのです。

sayHello(); // ← 本来は下にある関数を先に使っても動く

function sayHello() {
  console.log('Hello!');
}

これにより、「とりあえず動かせる」ことを優先する柔軟さが実現できたのです。


hoistingの対象になるもの、ならないもの

宣言の種類hoistingされるか?巻き上げられる内容
varされる宣言のみ(値は未定)
function(関数宣言)される本体ごと
let / constされるが「一時的死域(TDZ)」に入るエラーになる
関数式(const greet = function () {} など)されない実行不可(参照エラー)

TDZ(Temporal Dead Zone)とは?

letconst でも宣言自体はhoistingされますが、「使えるのは実際に宣言された行より下だけ」というルールがあります。この使えない領域のことを 一時的死域(TDZ) と呼びます。

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


Hoistingのデメリット

バグの原因になりやすい

console.log(score); // undefined
var score = 100;

これを見て「scoreがどこで定義されたか分からない」と感じたなら、あなたの直感は正しいです。

hoistingの存在は、コードの読みやすさや予測しやすさを下げるという面もあります。


まとめ:hoistingは「優しさ」から生まれた設計

  • hoistingとは「変数や関数の宣言が先頭に持ち上げられる」JavaScriptの仕様
  • JavaScriptが柔軟でエラーを出しにくくするために採用された仕組み
  • ただし、今では letconst などが登場し、予測しやすいコードを書くことが主流

今後の学習のヒント

今後は次のようなテーマを学ぶと、より理解が深まります!

  • TDZ(Temporal Dead Zone)の正確な理解
  • 関数式と関数宣言の違い
  • let/constとvarの使い分け
  • JavaScriptの実行コンテキストとスコープチェーン

初心者のうちは、varよりもletconstを使って、hoistingの影響を最小限に抑えるコードの書き方を習得するのがおすすめですよ!

セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。