スコープの基礎

作成した変数はすべての場所から使えるとは限らず、アクセスできるコード範囲(スコープ)が決まっている。どこからでもアクセスできるのがグローバル変数で、それが格納されている特別なオブジェクトをグローバルオブジェクトという。

ブラウザとNode.jsでは、スコープとグローバルオブジェクトに違いがある。

    文脈により意味がブレるが、当サイトではこのように使う。


    スコープ

    ある変数を参照しようとするとき、その変数名を検索する範囲をスコープという。

    まず、変数を使う位置(今いる場所)が関数内であればそこから検索を始めるが、より内側(内部)の関数内は対象外。見当たらないなら、一つ外側の関数から順に検索し、見つかったらその外側は探さず終了。それぞれの検索範囲がスコープ。


    ローカルスコープ、ブロックスコープ

    関数内で宣言された変数やブロック内({}の中)でletconst宣言された変数はローカル変数となり、その外側からは参照できない。これをローカルスコープという。

    ブロックの場合はブロックスコープともいうが、letconst宣言変数だけ。

    // ローカル変数はその関数・ブロック外から参照できない
    function 関数() {
      var ローカル = 1
    }
    
    if (true) {
      let ローカル = 2
        {
          const ローカル = 3
        }
      console.log(ローカル) // 2
    }
    
    // ReferenceError: ローカル is not defined
    console.log(ローカル)
    

    ブロック内のvar宣言変数はブロック外と同一スコープ

    {
      var トップ1 = true
      let ローカル = true
    }
    console.log(トップ1) // true
    
    // ReferenceError: ローカル is not defined
    console.log(ローカル)
    
    let トップ2 = true
    {
      // エラー: 同一スコープなので、一度let宣言したものはvarといえども再宣言できない。
      // var トップ2 = true // SyntaxError: Identifier 'トップ2' has already been declared
    }
    

    トップレベルスコープ

    そうして関数・ブロック内に見つからなかったら、いよいよ関数・ブロックの外側であるトップレベルスコープから変数を検索する。HTMLのscript要素やNode.jsのJavaScript(スクリプト)ファイルにおいて、関数・ブロックの外側で宣言した変数を指す。

    トップレベルスコープは、ブラウザではグローバルスコープになるのに対して、Node.jsではローカルスコープ(ただしREPLではグローバル)。


    グローバルスコープ

    トップレベルスコープでも見つからなかったら、最後は特別に用意されているグローバルオブジェクトのプロパティ名が変数名として検索される。これをグローバルスコープという。

    ObjectMathsetTimeoutといったビルトインオブジェクトや、グローバルスコープでの関数宣言やvar宣言されたグローバル変数は、グローバルオブジェクトのプロパティに格納される。

    グローバル変数はどの場所のコードからもアクセス可能となる。

    グローバルスコープになりそうでならないもの


    どこにも見つからなければエラー

    // ReferenceError: 非実在 is not defined
    console.log(非実在)