2009-10-11 18 views
8

私は無名関数にそのコンテキストで動作する必要があるとしましょうが、それが「ウィンドウ」にバインドされているのか、それとも未知のオブジェクトであるのかは異なります。Javascriptの無名関数の「this」(スコープ)を取得するには?

匿名関数が呼び出されたオブジェクトへの参照を取得するにはどうすればよいですか?

EDIT、いくつかのコード:

var ObjectFromOtherLibIAmNotSupposedToknowAbout = { 
    foo : function() { 
     // do something on "this" 
    } 
} 

var function bar(callback) { 
    // here I want to get a reference to 
    // ObjectFromOtherLibIAmNotSupposedToknowAbout 
    // if ObjectFromOtherLibIAmNotSupposedToknowAbout.foo is passed 
    // as callback 
} 

bar(ObjectFromOtherLibIAmNotSupposedToknowAbout.foo); 

あなたは合法的に、なぜ一体あなたがそのような何かをしたいん、頼むかもしれません。さて、私は最初に渡された引数を配列として解凍したかったのです。ただ、Pythonのように「*」演算子はありません:

>>> args = [1,2,3] 
>>> def foo(a,b,c) : 
     print a,b,c 
>>> foo(*args) 
1 2 3 

は、私がSOに掘って「)(適用」を使用するように指示postが見つかりました:「電流を使用するように起こっているので、

function bar(callback, args){ 
    this[callback].apply(this, args); 
} 

興味深いですこれがオブジェクト内にあれば "this"、そうでなければ "window"になります。

しかし、私は問題があると思う:

場合「(バー)」、それは動作しません、そのため、その後、「これは」、「バー()」コンテナを参照すると、オブジェクト自体です。

BTW、私はパラメーターとしてスコープを渡したくありません。

もちろん、引数と関数を文字列として連結してevalを使用することはできますが、私は何かクリーナーが見つからない場合にのみこれを使用したいと思います。もちろん

、それは(結局、それができる)だけでは不可能だ場合、その後、私はやります:

function foo(func, args) 
{ 
    eval("func("+args.join(", ")+");"); 
} 

EDIT 2:フルシナリオ、コメントで尋ねたよう。

私はqunitを使ってJavascriptでユニットテストを行っています。クールですが、例外が発生するかどうかを確認する方法がありません。

最も基本的なテストは、そのように行われます:アイデアはのようなものを作ることです

/** 
* Asserts true. 
* @example ok($("a").size() > 5, "There must be at least 5 anchors"); 
*/ 
function ok(a, msg) { 
    _config.Test.push([ !!a, msg ]); 
} 

:私はevalを取り除くことができれば

jqUnit.prototype.error = function(func, args, msg) 
{ 
    try 
    { 
     eval("func("+args.join(", ")+");"); 
     config.Test.push([ false, msg + " expected : this call should have raised an Exception" ]); 
    } catch(ex) 
    { 
     _config.Test.push([ true, msg ]); 
    } 
}; 

、それは素晴らしいことです。なぜ私はスコープをパラメータとして使用したくないのですか?異なるスコープを持つ20個の関数を参照しているコンテナをループして、手作業で記述するのではなくループ内ですべてテストする必要があるかもしれないからです。

+2

いくつかのコード例を教えてください。私はあなたが本当に欲しいものを理解するのにいくつかの困難を持っています –

+0

はい、あなたが探しているものがわかりません。いくつかのコードサンプルを提供してください。 – SolutionYogi

+0

あなたは正しいと思います。 –

答えて

6

電子サティス、

行うための唯一の方法は、電話を使用するか、正しい「コンテキスト」を設定するための方法を適用することです。

問題を解決するには、コールバック関数とそのコールバック関数に適用するスコープを受け入れるようにバー関数を変更します。

function bar(callback, scope) 
{ 
    callback.apply(scope); 
} 

bar(ObjectFromOtherLibIAmNotSupposedToknowAbout.foo, ObjectFromOtherLibIAmNotSupposedToknowAbout); 

また、「バインド」メソッドを使用することもできます。私はコメントで述べたように、それはの責任

です:

Function.prototype.bind = function(context) { 
    var fun = this; 
    return function(){ 
    return fun.apply(context, arguments); 
    }; 
}; 

さて、あなたはEDIT

bar(ObjectFromOtherLibIAmNotSupposedToknowAbout.foo.bind(ObjectFromOtherLibIAmNotSupposedToknowAbout)); 

、そのまま自分のバーの機能を離れて見えるように呼び出し元のコードを変更することができます正しいコールバック関数を渡すための呼び出しコード。あなたの 'bar'機能は、使用する範囲、期間を決定することができません。

var LibObject = { foo: function() { //use this inside method } }; 

var fooFunction = LibOjbect.foo; 
bar(fooFunction); 

はどのように適用範囲がどうあるべきかを理解しようとしている、例えばこれを取りますか?あなたが今「解析する」ためのものは何もなく、この作業を行うためにあなたの「棒」機能を変更する方法はありません。

+1

こんにちは、ありがとう、それは単体テストフレームワークのための少しの拡張子をハッキングするためのものです、私は手元にテストされた機能の範囲を持っていません。 –

+0

バーメソッドコールの作成を担当していますか? JSでは、関数はオブジェクトにアタッチされず、コール/適用を使用して明示的に指定しない限り、JSエンジンは使用するコンテキストを決定します。 – SolutionYogi

+0

私は1000回のテストを(qunitの構文で)特定のシグネチャで書かなければならないということはできません。それはAPIの一貫性を損なうことになります。大きな問題ではありませんが、この質問は人生や死の問題ではありません:-) –

関連する問題