最初にソースコードの説明を少し:
var obj={};
obj.plugin={
// object plugin property is an object that has create property defined here
// create property is a function that adds another properties to object in general
create: function(pluginname){
// this default value has got 'var' modifier - it is local and has scope of 'create'
var default_value='p1';
// f1 is a plugin's function - it does what a plugin creator implements
var f1 = function(){
// it encloses 'default_value' locally in 'create'
alert(default_value);
//define plugin properties
}
// the line below is the creation of a new property, which allows the object
// to call a method of name of a plugin; it assigns to the property of that name
// the f1 function closure, but local to actual execution of 'create';
// note the use of 'new' operator which copies the function making it independent
// from other calls of 'create'
obj[pluginname] = function(){return new f1();}
/*
run other code here
*/
return {
// this function allows you to change 'default_value' still in scope
// of the same call of 'create', thus effectively changing that one (locally - it's 'var');
f2: function(args){
default_value=args;
}
}
// after leaving this brace you leave the 'create' scope
}
// and the plugin object scope
};
今それがどのように機能するか:
これは、文字列で呼び出される関数である のobj.plugin.create('pluginA').f2('pa');
プラグイン プロパティを要求します。その関数を呼び出すために、js は呼び出しのコンテキストを作成します(実際には、スタック上の構造化オブジェクトです)。は引数としてスタックに置かれ、はローカル変数としてスタックに置かれます。その後、関数が実行されます。変数の初期化が最初に行われ、次にこの割り当てが行われます
create
'pluginA'
'pluginA'
default_value
f1
f2
create
obj[pluginname] = function(){return new f1();}
これによりpluginA
、オブジェクトにプロパティが作成されます。object
次に、ローカル関数 f1 がスコープ外でプロパティとしてグローバルに渡されることに注意してください。次にreturn
、スタックからすべてのローカル変数とすべての実パラメーターをポップし、呼び出しスコープをエスケープする戻り値を入れるステートメントがあります。その後、スコープは残されます。
ここでちょっとしたトリックが発生します。戻り値は、残されたスコープから「default_value」への参照を持つ関数を取得したオブジェクトです。実際、実際のオブジェクトはヒープに格納されていますが、スタックにはそれらへの参照しかないため、可能です。これは、default_value
まだヒープ上に存在し、f2
返されたオブジェクトの関数によって参照されていることを意味します。
がf2
呼び出されると、コントロールはf2
呼び出しスコープに入ります。で定義されているため、ヒープ上create
のオブジェクトへの参照があります。default value
そのオブジェクトにアクセスできるため、変更することもできます'pa'
。次にf2
、 の呼び出しスコープが残され、セミコロンの後に戻り値も残されます。関数には、それf1
への参照もありdefault_value
、現在は に等しくなってい'pa'
ます。そのf1
関数は、の'pluginA'
プロパティで「閉じられています」 object
。
これは、グローバルobject
がプロパティpluginA
、つまり関数 ( と名付けられたf1
) を持っていることを意味します。その関数には、オブジェクト (名前が付けられたdefault_value
) への参照があります。そしてそのオブジェクトは string'pa'
です。値は、常にアクセス可能な で間接参照を介してアクセス可能に保たれますobject
。
これobj.plugin.create('pluginB').f2('pb');
は、他のパラメーターでそれぞれ同じことを行うためpluginB
、オブジェクトにプロパティを作成します。の別の呼び出しなcreate
ので、まったく新しい を持っていdefault_value
ます。これは別のローカル インスタンスです。object
まったく同じ魔法が、別のプロパティ (pluginB) でその新しいオブジェクトをグローバルに閉じます。Create
新しい関数を囲む新しいオブジェクトを返しますf2
。それはその 'newer' にアクセスできますがdefault_value
、前の呼び出しのものとは何の関係もありません。返されたf2
別のオブジェクトで が呼び出されると、「new」が に変更default_value
され'pb'
ます。
その後、以下は自明です...
obj.pluginA(); // pa
obj.pluginB(); // pb