JavaScriptのスコープチェーン・変数参照の仕組みをGIFアニメで分かりやすく解説
Post on:2020年3月12日
JavaScriptのスコープチェーン・変数参照の仕組み、グローバルスコープ、ローカルスコープ、ブロックスコープについてGIFアニメーションで分かりやすく解説された記事を紹介します。

⚡️⛓JavaScript Visualized: Scope (Chain)
by Lydia Hallie
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
JavaScriptのスコープチェーンの仕組みをGIFアニメで分かりやすく解説
JavaScriptのスコープチェーンについてこの記事では解説します。
私は視覚学習者なので、GIFアニメで視覚的に説明することで、あなたの手助けをしようと思います😃
まずは、下記のコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
const name = "Lydia" const age = 21 const city = "San Francisco" function getPersonInfo() { const name = "Sarah" const age = 22 return `${name} is ${age} and lives in ${city}` } console.log(getPersonInfo()) |
getPersonInfo関数で、name, age, cityという変数の値を含む文字列「Sarah is 22 and lives in San Francisco」を返します。しかし、getPersonInfo関数にはcityという変数は含まれていません。
では、どのようにしてSan Franciscoであることを知ったのでしょうか🤨?
このJavaScriptを実行すると、最初にさまざまなコンテキストに対してメモリスペースが設定されます。デフォルトのグローバルコンテキスト(ブラウザのwindow、ノードのglobal)、そしてgetPersonInfo関数で呼び出されたローカルコンテキストがあります。そして各コンテキストにはスコープチェーンもあります。
上記のgetPersonInfo関数の場合、スコープチェーンは下記のようになります。
心配しないでください、この図はまだ理解する必要はありません。

getPersonInfo関数におけるスコープチェーン
スコープチェーンは基本的に、その実行コンテキストで参照可能な値(他のスコープ)への参照を含むオブジェクトへの参照チェーンです。チェーン⛓は、このコンテキスト内から参照できるすべての値です。スコープチェーンは、実行コンテキストが作成されたときに作成されます、つまり実行時に作成されます!
この記事では、スコープチェーンのみに注目します。
下記の例では、実行コンテキストのキーと値のペアがスコープチェーンが持つ変数への参照を表しています。

スコープチェーンが持つ変数への参照
JavaScriptエンジンがこれらをどのように理解するか見てましょう。
グローバルコンテキストのスコープチェーンには3つの変数、nameで値がLydia、ageで値が21、cityで値がSan Francisco、を参照しています。
ローカルコンテキストには2つの変数、nameで値がSarah、ageで値が22、を参照しています。
getPersonInfo関数の変数にアクセスしようとすると、JavaScriptエンジンは最初にローカルのスコープチェーンをチェックします。
最初にローカルのスコープチェーンをチェックする
ローカルのスコープチェーンには、nameとageへの参照があります!
nameの値はSarah、ageの値は22ですが、cityにアクセスしようとするとどうなるでしょうか?
cityの値を見つけるために、JavaScriptエンジンはスコープチェーンを辿ります。つまり、ローカルのスコープチェーンが参照している外側のスコープ(この場合はグローバルオブジェクト)で、変数cityの値を見つけることができるかを確認します。
cityがローカルにないので、JavaScriptエンジンは外側のスコープを探す
グローバルコンテキストでは変数cityを値San Fanciscoで宣言しているため、変数cityへの参照があります。これで変数の値を取得できたので、getPersonInfo関数は文字列「Sarah is 22 and lives in San Francisco」を返すことができます🎉
スコープチェーンを下ることはできますが、上ることはできません。下ではなく上と言う人もいるので混乱するかもしれませんが、言い換えると外側のスコープチェーンにはアクセスできますが、内側にはアクセスできません。
視覚化すると、滝のような動きをイメージしてください。

スコープチェーンは外側に下ることはできるが、内側に上ることはできない
さらに深い階層でも同じです。

深い階層でもスコープチェーンは下るだけ
コードでも確認しておきましょう。

スコープチェーンの流れをコードで確認
ほぼ同じですが、大きな違いが1つあります。
ここではgetPersonInfo関数でcityを宣言しただけで、グローバルスコープでは宣言していません。getPersonInfo関数を呼び出していないため、ローカルコンテキストも作成されません。
グローバルコンテキストでnameとageとcityの値にアクセスしてみます。
ReferenceErrorが返される
この場合、cityの値にアクセスすると、ReferenceErrorが返されます。
グローバルスコープでcityという変数への参照を見つけることができません。また、検索する外部スコープもなく、スコープチェーンを上に移動することもできません。
このように、変数を保護して変数名を再利用する方法としてスコープを使用することができます。
グローバルスコープとローカルスコープに加えて、ブロックスコープもあります。letまたはconstキーワードで宣言された変数は、最も近い中括弧({})にスコープされます。
1 2 3 4 5 6 7 8 9 10 11 |
const age = 21 function checkAge() { if (age < 21) { const message = "You cannot drink!" return message } else { const message = "You can drink!" return message } } |
これを視覚化してみます。

ブロックスコープ
グローバルスコープ、関数スコープ、2つのブロックスコープがあります。変数は中括弧にスコープされているため、変数messageを2回宣言することができます。
まとめます。
- スコープチェーンは、現在のコンテキストでアクセスできる値への参照のチェーンと考えることができます。
- スコープは、スコープチェーンの下位に定義された変数名を再利用することもできます。これは、スコープチェーンの上位ではなく下位にしか定義できないためです。
スコープチェーンの説明はこれで終了です。これについてはまだ言いたいことが山ほどあるので、時間があるときに追加するかもしれません。
困っていることがあれば、遠慮なく質問してください。私はあなたを助けたいと思います!💕
sponsors