作成した変数はすべての場所から使えるとは限らず、アクセスできるコード範囲(スコープ)が決まっている。どこからでもアクセスできるのがグローバル変数で、それが格納されている特別なオブジェクトをグローバルオブジェクトという。
ブラウザとNode.jsでは、スコープとグローバルオブジェクトに違いがある。
文脈により意味がブレるが、当サイトではこのように使う。
ある変数を参照しようとするとき、その変数名を検索する範囲をスコープという。
まず、変数を使う位置(今いる場所)が関数内であればそこから検索を始めるが、より内側(内部)の関数内は対象外。見当たらないなら、一つ外側の関数から順に検索し、見つかったらその外側は探さず終了。それぞれの検索範囲がスコープ。
関数内で宣言された変数やブロック内({}
の中)でlet
・const
宣言された変数はローカル変数となり、その外側からは参照できない。これをローカルスコープという。
ブロックの場合はブロックスコープともいうが、let
とconst
宣言変数だけ。
// ローカル変数はその関数・ブロック外から参照できない
function 関数() {
var ローカル = 1
}
if (true) {
let ローカル = 2
{
const ローカル = 3
}
console.log(ローカル) // 2
}
// ReferenceError: ローカル is not defined
console.log(ローカル)
{
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ではグローバル)。
トップレベルスコープでも見つからなかったら、最後は特別に用意されているグローバルオブジェクトのプロパティ名が変数名として検索される。これをグローバルスコープという。
Object
やMath
、setTimeout
といったビルトインオブジェクトや、グローバルスコープでの関数宣言やvar
宣言されたグローバル変数は、グローバルオブジェクトのプロパティに格納される。
グローバル変数はどの場所のコードからもアクセス可能となる。
let
・const
宣言の変数、class
宣言のクラス(トップレベルスコープでもそうなので、この意味でローカルスコープ)。// ReferenceError: 非実在 is not defined
console.log(非実在)