7

私は ParentObject.doSomething() を呼び出しています。これは、WebService オブジェクトを呼び出していくつかの ajax 呼び出しを実行し、ajax 呼び出しが成功すると、コールバック関数が実行されます。ただし、コールバック関数内の親関数は失敗します。

これはスコープの解像度と関係があると思います。この問題の回避策が見つかりません。

ajax サービスとモデルをモジュール化するためのより良いアーキテクチャ スタイルはありますか?

私もjsfiddleを作成しました - http://jsfiddle.net/bzKXr/2/

var ParentObject =  {

     doSomething: function(){
         document.write("Inside doSomething <br />");
         var self = this;
         WebServices.firstService("some URL", self.successCallback);
     },

     changeData: function(data){
         //Manipulate data
         document.write("Inside changeData <br />");
     },

     successCallback: function(jsonData){
         document.write("Inside successCallback <br />");
         try {
             //Execution fails at this point. Possibly because of scope resolution
             this.changeData(jsonData);  
         }
         catch (error) {
             console.log(error);
             document.write(error);
         }  
     },
};

var WebServices = {
    firstService: function(url, successCallbackHandler){
        document.write("Inside firstService <br />");
        //Get data using the URL
        //on success call successCallback
        successCallbackHandler("some data");
    }
};


$(document).ready(function() {
    ParentObject.doSomething();

});
​
4

5 に答える 5

11

書き込みself.successCallbackは関数を にバインドしません。コンテキストを正しくバインドするselfには、実際に関数を呼び出す必要があります。self.successCallback()

へのアクセスを保持するクロージャーで呼び出しをラップすることで、これを簡単に行うことができますself

doSomething: function(){
     document.write("Inside doSomething <br />");
     var self = this;
     WebServices.firstService("some URL", function() {
        self.successCallback();
     });
 },

またはES5では、コンテキストが常に指定されたパラメーター.bind()であることを保証するものを使用できます。thissuccessCallback

doSomething: function(){
     document.write("Inside doSomething <br />");
     WebServices.firstService("some URL", this.successCallback.bind(this));
 },
于 2012-07-24T12:25:22.717 に答える
2

これを行う最も美しい方法は次のとおりです。

WebServices.firstService("some URL", this.successCallback.bind( this ));

ただし、クロスブラウザではありません。(読む:IE8以下は使用できません)

これがjQueryが持っている理由$.proxyです:

WebServices.firstService("some URL", $.proxy( this.successCallback, this ));
于 2012-07-24T12:41:59.847 に答える
1

コールバック関数が呼び出されると、thisは無効になります。JavaScript では、関数が で呼び出された場合foo.bar()thisに設定されfooますが、 を呼び出すだけfoo()では、以前に設定thisされたものが保持されます。この場合、イベントの要素、おそらくWebService. これを回避するには、クロージャを使用する必要があります。で交換できthis.changeData(jsonData);ますParentObject.changeData(jsonData);。クロージャーとは、関数が定義されたスコープ内の変数に関数がアクセスできることを意味するため、関数はParenObjectにアクセスできます。

よりエレガントな方法は次のとおりです。

var ParentObject =  {

    doSomething: function(){
        document.write("Inside doSomething <br />");
        var self = this;
        WebServices.firstService("some URL", function(jsonData) {
            document.write("Inside successCallback <br />");
            self.changeData(jsonData);
        }
    },

    changeData: function(data){
        //Manipulate data
        document.write("Inside changeData <br />");
    }
};

コールバック関数は関数内で直接定義されてdoSomethingいるため、関数内で定義された変数にアクセスできself、 を呼び出すことができますself.changeData()

于 2012-07-24T12:33:58.217 に答える
0

別の可能性は変化です

WebServices.firstService("some URL", self.successCallback);

WebServices.firstService("some URL", function(data){ return self.successCallback(data) });

基本的な問題は、Python とは異なり、Javascript のメソッド Javascript は、別の場所に渡すか別の変数を設定するとすぐに所有者オブジェクトを忘れてしまうことです。

于 2012-07-24T12:27:51.080 に答える
0

に変更this.changeData(jsonData);するParentObject.changeData(jsonData);と動作するはずです。

エラーの理由は、AJAX 呼び出しが戻るときにthis変数が参照されなくなったためです。ParentObject

別のアプローチは、this別の変数内への参照を格納し (慣例によりthat)、コードを次のように変更することです。that.changeData(jsonData);

于 2012-07-24T12:24:50.120 に答える