0

異なるモジュールで変数を共有できるかどうか知りたいです。

たとえば、私のcommonモジュールでは、いくつかのグローバル変数とユーティリティ メソッドを定義しています。

(function(){
  var name="";
})();

name別のモジュールにいる間、たとえばモジュール内の変数にアクセスしたいapp

var kk=name; // access the name
//other thing

nameただし、グローバル コンテキストにエクスポートしたくありません。

出来ますか?

アップデート


私がこの質問をする理由は、Google がこれを行うのを見つけたからです。

Google マップのサンプル ページ:

次の js をロードします: main.js

内容は次のとおりです。

((function(){ //xxxxxx }).call(this);

次に、次のようにマップcompnets をロードします。

グーグルマップ。_ gjsload _ ('map', '\'use strict\';function Ut(){}function Vt(a,b,c).......');

モジュールはモジュールmap内の変数を使用できますがmain

4

2 に答える 2

1

編集:

それは完全に単純です: サンプル ページでコンソールを開いて main.js のソースを見ると (左下隅にある のようなボタンをクリックします[{}])、スクリプト全体が 1 つの大きな関数であることがわかります。を使用して呼び出され.call(this)ます。後者は、厳密モード (呼び出し元コンテキストとして明示的に設定されていない限り、グローバル オブジェクトを保護する) のために必要です。
この関数は、この関数のスコープ内のすべての関数、オブジェクト、およびメソッドを宣言し、クロージャーを形成します。したがって、このスコープで宣言されたすべての関数もすべての変数にアクセスできるのは当然のことです。最終的に、googleプロパティはグローバル オブジェクトのプロパティとして割り当てられるため、クロージャが公開されます。

(function()
{
    'use strict';
    console.log(this);//would be undefined
}).call(this);//but the global object is explicitly set as context, so this === window

(function()
{
    'use strict';
    var closureScope = 'Global object can\'t see me';
    var google = {visible:'Yes, I was assigned as a property to the global object'};
    google.closureScope = closureScope;//expose initial value of closureScopeVariable
    google.showBenefits = function()
    {//context here is google object, this points to google
        this.closureScope = 'I looked like the closure variable';//reassign
        console.log(this.closureScope === closureScope);//logs false
    };
    google.restoreOriginal = function()
    {
        this.closureScope = closureScope;//reassign closureScope's original value
    };
    //expose:
    this.google = google;
}).call(this);
//global object:
google.closureScope = 'Foobar';
google.restoreOriginal();
console.log(google.closureScope);//Global object can't see me

私が知っている限りでは、これはそれほど明確に見えないかもしれませんが、基本的に何が起こるかは次のとおりです。各関数には独自のスコープがあります。そのスコープで宣言されたすべての変数は、それらを参照するオブジェクトがない限り、その関数が戻るときにガベージ コレクション (GC) されます。
この場合、google は無名関数のスコープで宣言されたオブジェクトです。次に、この google オブジェクトへの参照がグローバル オブジェクトに割り当てられました。たまたまオブジェクト変数と同じ名前になっていますが、次のように公開することもできます。

window.foobar = google;
window.foobar.closureScope;//works
window.google;//undefined

Google はグローバル オブジェクトのプロパティであり、関数のスコープで作成されたオブジェクトを参照します。それが参照するオブジェクトは、関数のスコープ (およびそのスコープで宣言されたすべての変数) を維持します。そのため、クロージャー変数にほぼ直接アクセスできるように見えるかもしれませんが、これもREFERENCEです。C(++) プログラミングに精通している場合、疑似コードでは次のようになります。

GoogleObj google = new Google();
GoogleObj &window.google = google;
//or in pseudo-C:
GoogleObj *google;
GoogleObj **window.google = &google;//pointer to pointer ~= reference

基本的に、グローバルgoogleには実際のGoogleオブジェクトのメモリアドレス以外は何も含まれていません。それを指し、参照し、メモリ内の値を探す場所をJSに指示するだけです...
実際のオブジェクトに直接アクセスすることはできません。メモリのどこかに、それとともに宣言されたすべてのローカル変数もあり、それらにもすべてアドレスがありますが、グローバルオブジェクトはそれらについて知りません。知っている 1 つのアドレスに移動し、必要なものを要求すると、元のgoogle オブジェクトが従います。

私はこれらすべてを首尾一貫した包括的な方法で説明するのが苦手ですが、おそらくこの記事はこの問題に光を当てるかもしれません. クロージャーについて調べ始めたとき、図が非常に役立つことがわかりました。


そんなことはできません。クロージャーの要点は、その特定のスコープでのみ参照できる変数を設定できることです。ただし、できることは、特権メソッドを使用するか(良い習慣ではありませんが可能です) グローバル オブジェクトに変数を完全に割り当てることです。

(function()
{
    var name = 'foo';
    //do stuff
    window.name = name;//expose to global object
})();//THIS IS BLUNT AND DANGEROUS

var safer = (function()
{
    var name = 'foo';
    return {name:name};
});
console.log(safer.name);//logs foo

本当に、本当にグローバルが必要な場合:

var safer = (function()
{
    var closureVars = {name:'foo'};
    var name = 'foo';
    return function(privateName,globalName)
    {
        globalName = globalName || privateName;
        window[globalName] = closureVars[privateName];
    };
});
safer('name');//sets window.name to 'foo'

しかし、何よりも、特にあなたの場合(特定の「プライベート」変数にアクセスする)、特権ゲッターが最善の方法のようです:

var module = (function()
{
    var closureVars = {name:'foo';}
    return {get:function(name)
        {
            return closureVars[name];
        },
        set:function(name,val)
        {
            closureVars[name] = val;
        }
    };
};
var name = module.get('name');//sets a global name variable to 'foo'
module.set('name2',module.get('name'));//and so on

それはそれを行う必要があります

于 2012-09-14T11:38:52.673 に答える
0

クエンティンとエリアスの正しい批判の後に更新

モジュールを次のように定義できます。

var module = (function(){
    // your module definition
    var module = {};

    // set name as a property of the module
    module.name="";

    // return the module object
    return module;
})();

そして今、使用してモジュールの外部の名前にアクセスします

var kk = module.name;
于 2012-09-14T11:30:09.463 に答える