目次

JavaScript 変数のスコープ

y2sunlight 2021-04-05

var variable = 'グローバル変数';
function func(arg) {
    var variable = 'ローカル変数';
    return `${arg} ${variable}`;
}
console.log(func('引数'));  // 出力:'引数 ローカル変数'
console.log(variable );     // 出力:'グローバル変数'

グローバル変数

※ 変数とはvar又はletにより生成される。それらのないものはグローバルオブジェクトのプロパティとして扱われる。

ローカル変数

※ ローカル変数を作りたい時は常に var
※ ES2015以前はブロックスコープがなかった

var myVariable = 'Global Variable';
        
function func() {
    console.log(myVariable);  // 出力:undefined
    var myVariable;
    return myVariable;
}
        
console.log(func());  // 出力:undefined

var の位置に関わらず myVariable は関数内のどこでも常にローカルスコープを持つ。
var myVariable をコメントアウトするとグローバルスコープを持つようになる。
⇒ 変数の巻き上げ(hoisting)と呼ばれる。

ブロックスコープ

*2015

let(変数)又はconst(定数)によりブロックスコープを作る事ができる

let i = 1;
var j = 1;
const c = 1;
{
    let i = 2;
    var j = 2;
    const c = 2;
    console.log(`${i} ${j} ${c}`);  // 出力:2 2 2
}
console.log(`${i} ${j} ${c}`);  // 出力:1 2 1 ※varは上書きされている

Functionコンストラクタと関数リテラルのスコープ

var variable = 'Global Scope';

function func() {
    var variable = 'Local Scope'; 
    var func1 = new Function('return variable');
    var func2 = function(){return variable};
    var func3 = () => variable;
    
    console.log(func1());  // 出力:Global Scope
    console.log(func2());  // 出力:Local Scope
    console.log(func3());  // 出力:Local Scope
}

func();

Functionコンストラクタによるスコープはグローバルスコープを持つ。

Callオブジェクト

Call オブジェクト(Activation オブジェクトとも呼ばれる)は、関数が呼び出される度に内部的に自動生成されるオブジェクトです。関数の実行時に、引数とvar変数がCall オブジェクトに格納され、Arguments オブジェクトを参照するargumentsプロパティが生成されます。

スコープチェーン

スコープチェーンとは、グローバルオブジェクトとCall オブジェクトを連結したリストのことで、変数の名前解決のために使用されます。JavaScript は関数が呼び出されると、Callオブジェクトを生成しスコープチェーンの先頭に追加します。チェーンの最後にはグローバルオブジェクトが配置されています。

JavaScript の変数の名前解決には、このスコープチェーンが利用され、チェーン先頭から末尾のグローバルオブジェクトまでが検索され、チェーンに含まれない変数は、未定義になります。