このJavascriptをブラウザに取り込んでください。
<script>
console.log(window.someThing);
var x = 12;
function foo() {
window.otherThing = x;
}
</script>
foo
内でwindow
にアクセスできますが、それは誰もが知っていますが、なぜ正確なのですか?
script
タグ内)は暗黙のローカル変数としてそれを持っており、他のローカル変数(上記のx
など)のように単に「クロージャ継承」されていますか?でしょうか?そして、それは、script
のプロパティとして設定されているwindow
タグ内で直接宣言された変数とどのように一致しますか? (またはそうではありませんか?)
<script>
var x = 12;
function() {
console.log(window.x);
}
</script>
「スコープ外」または「無料」にアクセスできる理由)ECMAscriptの変数は、スコープチェーンと呼ばれるものです。スコープチェーンは、各実行コンテキストからの特別なプロパティです。前に何度か述べたように、コンテキストオブジェクトは少なくとも次のようになります。
コンテキスト(たとえば関数)内の変数(-name)にアクセスするたびに、ルックアッププロセスは常にそれ自体のActivation Object
で開始されます。すべての仮パラメーター、関数宣言、およびローカルで定義された変数(var)は、その特別なオブジェクトに格納されます。そのオブジェクトで変数名が見つからなかった場合、検索は[[Scope]]
チェーンに入ります。 function(-context)が初期化されるたびに、すべての親コンテキスト変数/アクティベーションオブジェクトが内部の[[Scope]]
プロパティにコピーされます。それが私たちが呼ぶもの、字句スコープです。これが、ClosuresがECMAscriptで機能する理由です。 Global context
にもVariable Object
があるため(より正確には、**グローバルオブジェクトの変数オブジェクトはグローバルオブジェクト自体です)、関数にもコピーされます [[スコープ]]プロパティ。
これが、任意の関数内からwindow
にアクセスできる理由です:-)
上記の説明には、1つの重要な概念上の結論があります。ECMAscriptの関数はすべてClosureであり、これは正しいです。すべての関数は少なくともグローバルコンテキストVOをその[[Scope]]プロパティ。
ウィンドウはJavascriptで本当にグローバルですか?
はい。より狭い範囲でwindowという新しい変数を作成しない限り
function foo() {
var window;
}
Fooの内部では、ウィンドウにアクセスできます。誰もがそれを知っていますが、なぜ正確なのですか?
どの関数も、より広いスコープで宣言された変数にアクセスできます。そこの窓には特別なことは何もありません。
それはすべてECMAScriptで定義されています。
グローバルは、外部の語彙環境を持たない語彙環境です。他のすべての環境はその中にネストされており、仕様で指定されたプロパティを持つグローバルオブジェクトにバインドされています。
これにより、グローバルオブジェクトのプロパティがスコープチェーンの先頭に配置され、そこから他のすべての環境が継承されます。
グローバル環境は、ECMAScriptコードが実行される前に作成される一意の字句環境です。グローバル環境の環境レコードは、バインディングオブジェクトがグローバルオブジェクト(15.1)であるオブジェクト環境レコードです。グローバル環境の外部環境参照がnullです。
ECMAScriptコードが実行されると、追加のプロパティがグローバルオブジェクトに追加され、初期プロパティが変更される場合があります。
一意のグローバルオブジェクトは、コントロールが実行コンテキストに入る前に作成されます。
特に指定のない限り、グローバルオブジェクトの標準の組み込みプロパティには、属性{[[Writable]]:true、[[Enumerable]]:false、[[Configurable]]:true}があります。
グローバルオブジェクトには[[Construct]]内部プロパティがありません。 new演算子を使用して、グローバルオブジェクトをコンストラクターとして使用することはできません。
グローバルオブジェクトには[[Call]]内部プロパティがありません。グローバルオブジェクトを関数として呼び出すことはできません。
グローバルオブジェクトの[[Prototype]]および[[Class]]内部プロパティの値は、実装に依存します。
この仕様で定義されているプロパティに加えて、グローバルオブジェクトには追加のホスト定義プロパティが含まれる場合があります。これには、値がグローバルオブジェクト自体であるプロパティが含まれる場合があります。たとえば、HTMLドキュメントオブジェクトモデルでは、グローバルオブジェクトのウィンドウプロパティはグローバルオブジェクト自体です。
それはスコープチェーンと関係があります。
以下をご覧ください ニコラスC.ザカスのプレゼンテーション 。 (5分頃から)
windowは、すべてのjavascriptオブジェクトの基本スコープであり、宣言の前に「var」を使用しない限り、定義した各変数に自動的に「アタッチ」されます。この場合、ローカルの変数のスコープです(つまり、ウィンドウは内部に含まれています。親関数、または関数ブロックの外部で変数を宣言している場合はグローバルでもあります)。さらにウィンドウは定数として定義されます、つまりウィンドウオブジェクトを再定義することはできません(「タイプエラー:constウィンドウの再宣言」というエラーが表示されます)。
そう:
window.foo = 5;
それは次と同じです:
var foo = 5;
または:
function() {
foo = 5;
}
だが:
function() {
var foo = 5;
}
この場合、「foo」はローカルです(window.foo === undefined)
window
グローバルスコープはメインスレッドにのみ適用されます。 Webワーカーには、window
グローバル変数はありません。代わりに、 WorkerGlobalScope
がWebWorker
内にあり、 SharedWorkerGlobalScope
がSharedWorker
内にあります。
このワーカーグローバルスコープは、self
という変数に格納され、MDNで説明されているように次のようになります。
このスコープには、通常 Window オブジェクトによって伝達される情報が含まれています。
これは、Webワーカーで使用しているサードパーティのコードがウィンドウオブジェクトを使用している場合に問題になる可能性があります。これは、@ FelipeMicaroniLalliが ここでの回答 で次のように提案しているように、window
変数を宣言することで簡単に解決できます。
var window = self;
本の中で Javascript:The Good Parts 、私が理解しているように、ダグラス・クロックフォードはwindow
がすべてのグローバル変数を含むWebブラウザのグローバルオブジェクトであると説明しています。それは一つの指輪のようなものです...