なぜ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)とは?
let
や const
でも宣言自体はhoistingされますが、「使えるのは実際に宣言された行より下だけ」というルールがあります。この使えない領域のことを 一時的死域(TDZ) と呼びます。
console.log(x); // ReferenceError
let x = 10;
Hoistingのデメリット
バグの原因になりやすい
console.log(score); // undefined
var score = 100;
これを見て「scoreがどこで定義されたか分からない」と感じたなら、あなたの直感は正しいです。
hoistingの存在は、コードの読みやすさや予測しやすさを下げるという面もあります。
まとめ:hoistingは「優しさ」から生まれた設計
- hoistingとは「変数や関数の宣言が先頭に持ち上げられる」JavaScriptの仕様
- JavaScriptが柔軟でエラーを出しにくくするために採用された仕組み
- ただし、今では
let
やconst
などが登場し、予測しやすいコードを書くことが主流
今後の学習のヒント
今後は次のようなテーマを学ぶと、より理解が深まります!
- TDZ(Temporal Dead Zone)の正確な理解
- 関数式と関数宣言の違い
- let/constとvarの使い分け
- JavaScriptの実行コンテキストとスコープチェーン
初心者のうちは、var
よりもlet
やconst
を使って、hoistingの影響を最小限に抑えるコードの書き方を習得するのがおすすめですよ!
セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク
投稿者プロフィール
