あなたが観察するものはlexical scopeと呼ばれます。これは、JavaScript の特定のスコープ内の変数のバインディングが、変数がコード内のどこに現れるかによって決定されることを意味します。それは常に真であり、どのレベルでも真です。唯一の主な例外は、字句スコープではなく動的スコープthis
の値です。動的スコープとは、関数内の変数が、関数が呼び出される方法とタイミングに依存することを意味します。(字句スコープと動的スコープを参照してください。)
例:
var o = {
a: function() {
var x = 5;
console.log(this, x);
function b() {
console.log(this, x);
}
b();
}
};
o.a();
この例の結果は次のようになります。
{Object o} 5
{window} 5
つまり、1つ目はオブジェクトへの参照としてconsole.log
ログに記録され、2 つ目はオブジェクトへの参照としてログに記録されます。ただし、どちらもに等しいとログに記録されます。の値は、非厳密モードでコンテキストなしで呼び出された場合です。Soはレキシカルにスコープされていませんが、他の変数は同様です。の動作の詳細については、の概要を参照してください。this
o
console.log
this
window
x
5
this
window
this
x
this
this
質問に直接答えるには:
1. まず、これは常に正しいのですか? または厳しい状況がありますか?(のように、それはオブジェクトである必要がありますか?など)
はい、関数の呼び出し方法に基づいて変化するthis
とを除いて、それは当てはまります。arguments
オブジェクトである必要はありません。すべての変数はレキシカル スコープです。
2. また、javascript には、このような不明瞭なスコープが他にどのようなものがありますか? 知りたいです(つまり、3回目の反復はどうですか?)
必要なだけ深くすることができます。内部関数は常に外部関数の変数にアクセスできます。
function a() {
var x = 1;
console.log('a:', x);
return function b() {
var y = 2;
console.log('b:', x, y);
return function c() {
console.log('c:', x, y);
};
};
}
var foo = a(); // => logs 'a: 1'
var bar = foo(); // => logs 'b: 1 2'
bar(); // => logs 'c: 1 2'
これは、実際にはクロージャーと呼ばれる別のトピックの一部であり、別の関数内から関数を返すときに発生します。
3. 最後に、javascript スコープに関する高度な概念を説明するドキュメントを読んでもまったく問題ありません。誰か良いものを知っていますか?
すでにいくつかのリソースにリンクしています。別の良いもの:
MDN: 関数と関数のスコープ(具体的にはNested Functions and Closuresのセクション)。
また、クロージャーに関するものを読むことでメリットが得られます。また、レキシカル スコープを調べることもできます。