使用回调处理程序在函数内调用父对象方法

时间:2012-07-24 12:21:33

标签: javascript callback

我正在调用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();

});
​

5 个答案:

答案 0 :(得分:10)

编写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()来确保this的{​​{1}}上下文始终是指定的参数:

successCallback

答案 1 :(得分:2)

这是最漂亮的方法:

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

但是,它不是跨浏览器。 (阅读:IE8及以下版本不能使用它)

这就是为什么jQuery有$.proxy

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

答案 2 :(得分:1)

调用回调函数时,this无效。在javascript中,如果使用foo.bar()调用某个函数,this将设置为foo,但如果您只是调用foo(),则先前设置的thisWebService在你的情况下,保留事件的元素,可能是你的this.changeData(jsonData);。 为避免这种情况,您必须使用闭包。您可以ParentObject.changeData(jsonData);替换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 />"); } }; 。闭包意味着函数可以访问定义函数的作用域中的变量,因此您的函数可以访问ParenObject。

更优雅的方式可能是:

doSomething

您的回调函数直接在self函数中定义,因此您可以访问其中定义的变量self.changeData(),并且可以调用{{1}}。

答案 3 :(得分:0)

如果您将this.changeData(jsonData);更改为ParentObject.changeData(jsonData);则应该有效。

错误的原因是当AJAX调用返回时this变量不再引用ParentObject

另一种方法是将this的引用存储在另一个变量中(按照惯例that)并将代码更改为that.changeData(jsonData);

答案 4 :(得分:0)

另一种可能性是改变

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

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

基本问题是,与Python不同,Javascript中的Javascript方法只要您将其传递给其他地方或设置另一个变量就会忘记它们的所有者对象。