2012-01-24 8 views
2

背景:JQueryとFacebook Javascript APIを使用するwebappを構築しています。一部のユーザーはFacebookを好まないので、Facebookを使用しないことを望むユーザーに必要なID APIをエミュレートするサンクレイヤーも構築しました。物事をきれいに保ち、コードの重複を避けるために、Javascriptコードをいくつかのクラスにまとめました。OO Javascriptコールバック:私はそれを正しくしていますか?

Facebook APIとJQuery APIの両方がコールバックを大量に使用しています。

読みやすさのために
var obj_ref = this; 
some_jquery_function_that_takes_a_callback(/* various args */, 
    function() { obj_ref.my_callback_method(); }); 

は、obj_refobjが実際にクラスの名前です:私のすべての機能をオブジェクトにバインドされているので、私は頻繁に次のパターンを使用していことがわかりました。

シンプルで鮮明ないくつかの素晴らしいJavascriptの魔法がありますか?

更新:これまでのところ、良い解説がいくつかあります。コールバックメソッドは一般的に、クラスにバインドされた変数または関数を参照する必要があると付け加えておきます。必要がなければ、無名の関数ラッパーは不要です。

Update2:ベストアンサーを選択しましたが、すべての回答を慎重に読んでください。それぞれは、可能な解決策についてのいくつかの有用な洞察を提供します。

var x = 42; 
jQuery_something({}, function(y, z) { obj_ref.callback(x, y, z) }); 

をそして、あなたは、コールバックを自分に渡される引数をコントロールしていないので、それは次のようになります。

+1

+1「私はこれをやっていますか? – pduersteler

答えて

2

あなたobj_refであるためにあなたのthisを必要と日付のJavaScript(悲しいことに、あなたはおそらくできない)にアップデートをとることができる場合は、ラッパーを廃止するbindを使用することができます。

を作成します。呼び出されたときに、提供されたこの値のコンテキストでこの関数を呼び出す新しい関数。新しい関数が呼び出されたときに指定された引数のシーケンスが指定されたシーケンスの前に置かれます。

次に、あなたのオブジェクトやこれにあなたの方法をバインドできます。

some_jquery_function_that_takes_a_callback(/* various args */, 
    function() { obj_ref.my_callback_method(); }); 

は同じのようになります。そして、

// In some initialization pass... 
obj_ref.my_callback_method = obj_ref.my_callback_method.bind(obj_ref); 

// And later... 
some_jquery_function_that_takes_a_callback(/* various args */, 
    obj_ref.my_callback_method); 

thismy_callback_methodが呼び出されたときobj_refだろう。

また、Underscore.jsをプルして、bindまたはbindAllを使用することもできます。すべてを望んでいない場合、Underscore.jsから常にbindまたはbindAllを取得できます。

それとも、あなたはすでにプレイ中のjQueryを持っているので、あなたが標準bindの代わりに$.proxyを使用することもできます。

は、機能を取り、常に特定のコンテキストを持つことになり、新しいものを返します。

だから、このようにそれを行うことができます:

// In some initialization pass... 
obj_ref.my_callback_method = $.proxy(obj_ref.my_callback_method.bind, obj_ref); 

// And later... 
some_jquery_function_that_takes_a_callback(/* various args */, 
    obj_ref.my_callback_method); 

bindのjQueryのバージョンについての私に思い出さためdsfqに感謝を。呼び出しコンテキストを維持するために、あなたのオブジェクトへのバインディングを使用する

+2

jQueryには組み込みの 'proxy'関数があります。 – dfsq

+0

@ dfsq:思い出してくれてありがとう、私は過去1年間Backboneを使用していたので、私はUnderscoreに達する傾向があります。 –

0

私は余分なパラメータを渡すために持っているとき、私は通常のみの関数でコールバックを包みます。しかし、これは、範囲内のいくつかのvarへの参照が必要な場合にのみです。そして、場合によっては、varをキャプチャするためにクロージャを作成する必要があることを意味します。ループで。

しかし、それはケースはない場合、私はちょうど直接関数への参照を渡す:コールバックの参照は、この特定の例では、スコープ内にあるので、

jQuery_something({}, obj_ref.callback); 

さえthisは、正常に動作する必要があります(そうなしobj_ref最初にそれをコピーする必要があります。

明らか
jQuery_something({}, this.callback); 

、最後の例は、それを取得と同じくらいシンプルでクリーンである:「jQueryのメソッドのコールバック引数がこのオブジェクトのメソッド名ですd 'コールバック' '

+0

コールバックメソッドがクラスにバインドされた変数または関数を参照していない限り、これは機能します。私は私の質問を更新します。 – ObscureRobot

+0

私が正しく理解していれば、後者の例はコールバック内で呼び出された場合には機能しません。 – Alnitak

0

はい、これは間違いありません。あなたはいくつかのコードを保存するためにパターンを実装するヘルパー関数を持つことができます。

1

ベター:

var objRef = this; 

// #1. In this case you will have wrong context inside myCallbackMethod 
// often it's not what you want. e.g. you won't be able to call another objRef methods 
someJqueryFunction(a, b, objRef.myCallbackMethod); 

// #2. Proper way - using proxy (bind) function 
someJqueryFunction(a, b, $.proxy(objRef.myCallbackMethod, objRef)); 
1

私はコールバックと同じ問題を抱えています。ここで私はそれをどのように処理したのですか。

  • dfsqと同様に、$ .proxyがあなたの仕事をします。アンダースコアのような余分なライブラリは必要ありません。
  • アンダースコアjsには、$ .proxyのような独自のバインド関数があります。
  • 適用と呼び出し(関数で呼び出すことができるjavascriptメソッド)はうまく動作します。

のは、私は、オブジェクトを持っているとしましょう:

var Dog = { 
    name : "Wolfy", 
    bark : function(){ 
    console.debug(this.name," barks!"); 
    } 
} 

var AnotherDog = { 
    name : "Fang" 
} 

Dog.bark.call(AnotherDog); //--> Fang barks! 
Dog.bark(); //--> Wolfy barks! 

あなたの「クラス」を書くとき、あなたはコールバックの呼び出しを処理するために、このパターンを使用することができます。

あなたは、彼らがこれに似た何かをどのプロキシまたはバインドわからない場合:

var Dog = { 
    name : "Wolfy", 
    bark : function(){ 
    console.debug(this.name," barks!"); 
    } 
} 

Dog.bark = funciton(){ 
    var scope = Dog; 
    return Dog.bark.apply(scope,arguments); 
} 

は、元の関数の結果を返す新しい機能でそれをラップすることにより、樹皮機能を書き換え特定のスコープを使用するよう強制します。

関連する問題