スコープ関係は基本的な話だと思うのですが、いまだに悩まされることが多いです。今回はスコープチェーンと呼ばれる仕組みについてです。
引用します。
JavaScript では関数内で宣言された変数は、その関数内でしか見ることが出来ない。関数内に変数が見つからなかった場合、外側のスコープに変数を探しにいく。この仕組みをスコープチェーンと呼ぶ。(引用終わり)
前半は関数のスコープについて書いてあります。スコープチェーンは、関数内で宣言されていない変数については、関数の外に探しに行くよ、ということらしいです(同じ内容を繰り返し書いているだけな気もしますが……)。
具体例を見てみましょう。以下、プログラムを引用します。
var val = 10; var myFuncA = function() { return val; } var myFuncB = function() { var val = 1000; return val; } console.log(myFuncA()); console.log(myFuncB()); console.log(myFuncA());
この場合の出力結果は以下のようになります。
10 1000 10
ところが、次の場合には結果が変わってしまいます。
var val = 10; var myFuncA = function() { return val; } var myFuncB = function() { val = 1000; return x; } console.log(myFuncA()); console.log(myFuncB()); console.log(myFuncA());
10 1000 1000
(引用終わり)
1つめではmyFuncB関数の中でvalが変数として宣言されているため、return valで外にvalを探しに行かずに済んでいます。つまり外のvalは変更されていないわけです。
一方2つめでは、myFuncB関数の内部でvalが変数として宣言されていません。この場合、val = 1000 の時点で、関数の外にまでvalを探しにいき、代入してしまっているわけです。それで、return x (とありますが、return valの間違いではないでしょうか……)の後もval = 1000 のままになってしまっているということです。
参考:http://www.sirochro.com/note/js-about-closure/
http://www.sirochro.com/note/js-var-different/