10

グローバル オブジェクトは、トップレベルのレキシカル環境 (必要に応じて、スコープ チェーンのトップ) として機能します。これは、直接参照 (変数など) を介してグローバル プロパティにアクセスできることを意味します。

// global code
this.foo = 1;        // creating a global property
foo                  // accessing the global property via a direct reference

これは、プロパティ参照を介してグローバル変数にアクセスできることも意味します。

// global code
var foo = 1;         // creating a global variable
this.foo             // accessing the global variable via a property reference

解釈 1

ここで、上記の情報に基づいて、「グローバル変数」と「グローバル プロパティ」という用語を同じ意味で使用することが適切であるように思われます。つまり、両方の用語がグローバル バインディングのまったく同じセットを表すことを意味します。


varただし、 ,egを使用して作成されたグローバル変数var foo = 1;と、割り当てによって作成されたグローバル プロパティには、次の 2 つの違いがありますthis.foo = 1;

  1. グローバル変数は静的にスコープされますが、グローバル プロパティはグローバル環境に動的に追加されます。

    foo // => undefined
    bar // throws ReferenceError
    
    var foo = 1;
    this.bar = 1;
    

    そのため、グローバル変数はプログラムの評価前にバインドされますが、グローバル プロパティはプログラムの評価中にバインドされ、代入が評価されます。

  2. つまり、グローバル変数は削除できません (具体的には、対応するバインディングを後で環境から削除することはできません) が、代入によって作成されたグローバル プロパティ構成可能です。

    // the names "foo" and "bar" are bound to the global environment
    var foo = 1;
    this.bar = 1;
    
    // the binding "bar" can be removed from the global environment subsequently 
    delete this.bar; 
    
    // the binding "foo" cannot be removed subsequently
    

そうは言っても、構成不可能なグローバル プロパティを作成できることに注意してください。

Object.defineProperty( this, 'bar', { value: 1 }); // non-configurable by default

解釈 2

現在、この新しい情報に基づいて、静的にスコープされたグローバル バインディングのみがグローバル プロパティとグローバル変数の両方として参照される可能性があると言えますが、動的に追加されたグローバル バインディングは単なるグローバル プロパティであり、グローバル変数ではありません。 variable" は、次のように、"global property" という用語で表されるセットのサブセットを表します。

すべてのグローバル変数はグローバル プロパティ
です 静的スコープのグローバル プロパティのみがグローバル変数です


では、どの解釈が正しいのでしょうか。両方の用語は同じ束縛のセットを表していますか、それとも一方が他方のサブセットですか?


質問

「グローバル プロパティ」という用語は理解しています。グローバル プロパティは、グローバル オブジェクトのプロパティです。ただし、「グローバル変数」という用語はあいまいなようです。var「グローバル プロパティ」の同義語として使用する人もいれば、ステートメントを介して定義されたグローバル プロパティを意味すると定義する人もいます。私の質問の意図は、これら 2 つの意味のどちらが正しいかを判断することです。

4

2 に答える 2

5

ええと、変数のエッジ ケースと に関連付けられているプロパティを区別するために私が言ったことはすべて既にご存じでしょうwindow

本当に、本当にペダンティックになりたい場合は、グローバルスコープを機能スコープwindow、プログラム内で提供されるものと同じ非表示の構成設定を使用してプロパティでオブジェクトを拡張するスコープの両方であると考えることができると思います(例: 変数は再割り当てできますが、削除できません)。その意味で、機能に関する限り、それらは異なり、グローバル スコープのプロパティと変数の属性を反映します。

そして、それらをそのように参照することはまったく問題ありません。
しかし、大多数の人々は、2 つの用語の違いは言うまでもなく、その違いを認識していません。
重要な JS 作成者でさえ、実際には JS が関数スコープをスケーリングするのに をglobal variable省略して誤って a を設定することに言及しvarており、その名前をヒットせずにグローバル スコープに到達するglobal propertyと、a ではなくそのデータに a を追加します。 global variable.

しかし、それは本当に核心につながります.強力で安定した信頼性の高いJSアプリケーションは、他のアプリケーションと一緒に最新のWebページに存在し、実際には違いをあまり気にするべきではありません.
その場合の目標は、できるだけ少ないグローバル プロパティと変数を使用することです。

さらに、変数/プロパティの衝突の危険性は、どちらであっても同じです。
変数は影響を受けませんが、有用なプログラムが設定されていないプロパティにdeleteアクセスする可能性はどのくらいありますか?delete

個人的には、エッジケースを理解するのは良いことだと思いますが、私の中の衒学者は違いがあることに同意したいと思っていますが、それらは同じものではありませんが、私の中の実用主義者は、人々がグローバル スコープを積極的に使用しており、これが彼らに大きな違いをもたらしています。

于 2012-10-02T15:30:02.803 に答える
2

良い説明はここにありますが、質問に答えるために短くします。あなたが言う時:

両方の用語は、グローバル バインディングのまったく同じセットを表します。

...あなたはほぼ正しいですが、完全ではありません。のようなプロパティの割り当ては、グローバルオブジェクトthis.foo = 1に保存されます。ただし、変数宣言は変数オブジェクトに保存されます。var bar = 2

グローバル スコープで実行する場合、グローバル オブジェクトと変数オブジェクトの両方が同じオブジェクト、つまりグローバル オブジェクトによって表されます(ブラウザで実行する場合は、これがwindowオブジェクトです)。

あなたの説明だけではこのプログラムの動作を説明するには不十分なので、これについて言及します。

// "this" refers to the global object. But global object is also acting as the
// variable object! Because of that, the following code works:

var foo = 1;
alert(this.foo);   // 1

(function() {

    // "this" still refers to the global object! But the *variable* object has
    // changed because we're now in the execution context of a function, thus
    // the behavior changes:

    var bar = 2;
    alert(this.foo);  // 1
    alert(this.bar);  // undefined

})();

ただし、これは、グローバル プロパティとグローバル変数が同一であることを意味するわけではありません。すべてのプロパティには、 、 、および の 3 つの隠しフラグがReadOnlyありDontEnumますDontDelete

のような暗黙的なプロパティ宣言を使用する場合this.foo = 1DontDelete属性は に設定されfalseます。のような変数宣言を使用するvar bar = 2と、DontDelete属性が に設定され、演算子trueを使用したときにそれらの違いが表されます。delete


あなたの言い換えられた質問に答えて:

[T]「グローバル変数」という用語はあいまいなようです。「グローバル プロパティ」の同義語として使用する人もいれば、var ステートメントを介して定義されたグローバル プロパティを意味すると定義する人もいます。私の質問の意図は、これら 2 つの意味のどちらが正しいかを判断することです。

この用語は明確に定義されていないため、意見を求めているだけです。

一般に、構文 を使用して変数を作成する場合は「グローバル プロパティ」という用語が使用され、構文 を使用してthis.foo = 1変数を作成する場合は「グローバル変数」という用語が使用されますvar bar = 2。もう議論することは何もありません。

どちらの用語も、舞台裏で行われていることとはまったく関係がありません。したがって、できることは、舞台裏で実際に何が行われているかを理解することです。これは既に行っています。

2 つの恣意的な用語について絶対的な定義をさらに要求すると、単に人気のない人物になるだけです。

于 2012-10-02T15:40:07.357 に答える