Javascript Scope
core javascriptの根本的な話。
僕らの愛するjavascriptには以下の二つのスコープがある。
- グローバル
- ローカル
- (ブロック: ex.next的な)
javascriptにおけるスコープの仕組みは少し特別なので説明する。
scope of each scopes
まずは、二つのスコープの範囲
var scope = 'Global Scope'; console.log(scope); // Global Scope [1] function hoge() { var scope = 'Local Scope'; console.log(scope); // Local Scope [2] } console.log(scope); // Global Scope [3]
これが何を意味するかというと、Javascriptにおいては関数内(この場合だとhoge関数)でvarを使って宣言された変数はすべてローカル変数になるということだ。
そしてローカル変数は関数内でしか存在することができず、[3]のような関数外での呼び出しで呼ばれることはなく、その場合は元のグローバル変数が参照されるのである。
Global Object and Activation Object
そもそも『グローバル変数やローカル変数を宣言する』ということはjavascriptにおいてどういう意味なのか。
それを学ぶためには以下の二つのオブジェクトについての知る必要がある。
- Global Object
- Activation Object*1
この二つのオブジェクトはArrayとかと違って少し特別で実装者側がnewしてインスタンスを得ることもできない。
これらの生成されるタイミングは以下の時だけである。
Global Object : js自体の実行時に内部的に作られる。
Activation Object : 関数呼び出しの際に内部的に作られる。
先ほどのソースをこれらを踏まえてみてみると以下のようになる。
// Global Objectが内部生成される var scope = 'Global Scope'; console.log(scope); // Global Scope [1] function hoge() { // この関数が呼び出された時、内部的にActivation Objectが生成される var scope = 'Local Scope'; console.log(scope); // Local Scope [2] } console.log(scope); // Global Scope [3]
さらにこれらのオブジェクトは生成されるタイミング以外にも特殊な動きを持っている。
それはプロパティ宣言方法だ。
実はこれらのオブジェクトが生存している段階でvarを用いて宣言した変数はそれぞれのオブジェクトのプロパティになるようになっている。
ソースでみてみると以下のようになっている。
// Global Objectが内部生成される var scope = 'Global Scope'; // Globalオブジェクトのプロパティにscopeを追加した。 console.log(scope); // Global Scope [1] function hoge() { // この関数が呼び出された時、内部的にActivation Objectが生成される var scope = 'Local Scope'; // Activationオブジェクトのプロパティにscopeを追加した。 console.log(scope); // Local Scope [2] } console.log(scope); // Global Scope [3]
Activationオブジェクトは大抵の場合、関数の処理を抜けた時点で消滅する。
そのため、ローカルスコープ内で宣言した[2]のscope変数は[3]の時点では参照できなくなっているのである。
こうした仕組みによってjavascriptの2つのスコープは実現されているのである。
何の役にも立たないように思えるが後にクロージャやらプロトタイプベースの継承やらを学ぶときにこれを知らないと何も理解できないので心に留めておいてほしい。
*1:Activation Objectは別名Call Objectととも言います