web-dev-qa-db-ja.com

JavaScriptのグローバル名前空間とクロージャを理解する

私はJavaScriptのグローバル名前空間の理解を深めようとしているのですが、いくつか興味があります。

  1. すべてのオブジェクト(プリミティブを除くすべてのものはオブジェクトであるため)に応答する "GOD"(つまり、親)オブジェクトはありますか?その場合、そのオブジェクトは "ウィンドウ"になりますか?

  2. vars/functionsをグローバルレベルで持つのが悪いのはなぜですか?

  3. vars/functionsをグローバルスコープに含めるのが本当に悪い考えである場合、クロージャがこれを回避するための最良の方法でしょうか?例:

    function parent(){
        var x = 'some value';//this var would be considered global to all children functions but not in the true global namespace
        function child1(){
            x.someMethod()
        } 
        function child2(){
            x*something;
        }
        function child3(){
            x+=something;
            child2()
            child1()
        }
        child3()
    }
    parent()
    
31
zero
  1. god(つまり、親)オブジェクトはありますか?

    はい。 より厳密には、これらすべてのプリミティブがメンバーとなっているのはグローバルオブジェクトです。ブラウザーでは、windowオブジェクトがグローバルオブジェクトであるだけです。

    _> window.String === String;
    true
    _
  2. Vars/functionsをグローバルレベルで持つのが悪いのはなぜですか?

    サードパーティのライブラリ/スクリプトを多数追加する場合、それらはすべて同じグローバルオブジェクトを共有するため、名前が競合する可能性があります。これは、_$_をエイリアスとして使用するすべてのライブラリ(jQuery、Prototypeなど)の実際の問題です。

  3. Vars/functionsをグローバルスコープに含めるのが本当に悪い考えである場合、クロージャがこれを回避する最良の方法でしょうか?

    xはグローバルと見なすべきではありません。これは、parent()関数内で子関数を宣言することによって形成されるクロージャの一部です。スニペットのproblem部分は、parent()がグローバルであることです。他のコードがparent()を再宣言するとどうなりますか?これは良いでしょう:

    _(function () {
    
    function parent(){
        var x = 'some value';
        function child1(){
            x.someMethod()
        } 
        function child2(){
            x*something;
        }
        function child3(){
            x+=something;
            child2()
            child1()
        }
        child3()
    }
    parent()
    
    }());
    _

    xが子関数内でアクセスできるという事実は悪くありません。これらの関数を自分で作成する必要があるため、xの存在をawareする必要があります。これらの子関数内でxvarで再宣言しても、parent()xは影響を受けないことに注意してください。

26
Matt
  1. はい、ブラウザ環境では「神オブジェクト」はウィンドウです。通常、global objectと呼ばれ、god objectではなく;)In nodejsなどの非ブラウザー環境では、グローバルオブジェクトはウィンドウ以外の名前を使用する場合があります。

  2. すべてをグローバルとして配置すると、名前が衝突する危険があります。 encapsulation の問題もあります。つまり、必要なスコープにのみ変数を配置することで、コードのパフォーマンスが向上します。

  3. うん、これはかなり好ましいアプローチです。 [〜#〜] iife [〜#〜] を使用することもできます

5
  1. 私の知る限り、そうだと思います。ウィンドウは親オブジェクトです。ただし、iframe内には独自のウィンドウオブジェクトがあり、window.parentを介してアクセスできる周囲のウィンドウとは異なります。

  2. 名前の衝突の可能性があり、バグを検出することが難しいため、グローバル変数のLOTを多く持つことは悪い考えです。一般に、名前空間を設計する方が安全です($ jQueryなどから)コードをモジュール化します。

  3. 注意してください、parentはウィンドウの潜在的な既存のフィールドです。この取られたアパート、機能は目的なので、2)と同じ観察がここに当てはまります。

3
Nicocube

[〜#〜] need [〜#〜]変数をグローバル名前空間に配置する場合、ある時点で単一のオブジェクト変数を作成し、他の変数をプロパティとして追加しますまたはメソッド。他のユーザーが使用する可能性の低い名前をオブジェクトに付けます(確かに、ここで衝突の問題が発生しますが、注意深く標準化された名前を付けることで軽減できます)。

例えばの代わりに:

var thing1 = 'table';
var anotherthing = 'chair';
var mypet = 'dog';
var count = 4;
var show_something: function( _txt ) { return _txt.trim(); };

これを行う:

var cmjaimet_obj = {
  thing1: 'table',
  anotherthing: 'chair',
  mypet: 'dog',
  count: 4,
  show_something: function( _txt ) { return _txt.trim(); }
};

その後、それらをプロパティとして呼び出します。

例えばの代わりに:

count += 2;
anotherthing = 'sofa';
console.log( show_something( 'Thing: ' + anotherthing ) );

これを行う:

cmjaimet_obj.count += 2;
cmjaimet_obj.anotherthing = 'sofa';
console.log( cmjaimet_obj.show_something( 'Thing: ' + cmjaimet_obj.anotherthing ) );
3
Charles Jaimet