====== JavaScript 変数のスコープ ======
--- //[[http://www.y2sunlight.com/water|y2sunlight]] 2021-04-05//
var variable = 'グローバル変数';
function func(arg) {
var variable = 'ローカル変数';
return `${arg} ${variable}`;
}
console.log(func('引数')); // 出力:'引数 ローカル変数'
console.log(variable ); // 出力:'グローバル変数'
\\
===== グローバル変数 =====
* 関数の外でvarにより宣言された変数
* varを使用しない全ての変数はグローバル変数として扱われる
※ 変数とはvar又はletにより生成される。それらのないものはグローバルオブジェクトのプロパティとして扱われる。
\\ \\
===== ローカル変数 =====
* 関数内でvarにより宣言された変数
* 仮引数
※ ローカル変数を作りたい時は常に ''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'')と呼ばれる。
\\ \\
===== ブロックスコープ =====
[[js:top#ECMAScript|*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 の変数の名前解決には、このスコープチェーンが利用され、チェーン先頭から末尾のグローバルオブジェクトまでが検索され、チェーンに含まれない変数は、未定義になります。