基本的にはJavaScriptは現在のスコープからグローバルに向かって参照が行われます。
…が、少し想像していた動きと違ってしまうことがあったので調査してました。
test.js
var x = 0;
function a() {
var x = 1;
function b() {
console.log("func b:x=" + x);
}
function c(v) {
x = v;
}
return {"b":b,"c":c};
}
console.log("Hello!");
console.log("x=" + x);
func = a();
func["b"]();
x=10;
console.log("x=" + x);
func["b"]();
console.log("x=" + x);
func["c"](15);
console.log("x=" + x);
func["b"]();
console.log("x=" + x);
次に実行結果を。
result.log
Hello! // こんにちは
x=0 // グローバルのxは今日も0なのである
// ここで関数aから関数bとcを取り出す
func b:x=1 // おそらく関数a内のxが参照されている
// グローバルのxを10に書き換える
x=10 // グローバルのxは書き換わったようだ
func b:x=1 // しかし関数bの返り値であるxは書き換わっていない
x=10 // しつこく見てみるが、グローバルのxも書き換わっていない
// そこで関数cによってxを書き換えてみる
x=10 // グローバルのxは書き換わらない
func b:x=15 // 関数a内のxは書き換わっている
x=10 // やっぱり書き換わってない
最近の言語は単純なスタックモデルを想定しているとうまく行かないのですね。
自分は関数aの変数xは関数x終了時に破棄されると思っていました。
この結果だと、関数bとcがアクセスできる状態であれば関数aの変数xも生きているようです。
ちゃんと書いてありました。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Functions#Preservation_of_variables
この場合、関数bとcがアクセスできなくなった場合にメモリが開放されるということで。