2014-05-18 114 views
2

我正在构建一个使用OOP原则的jQuery应用程序,我试图实现一个外部添加的回调函数,该函数从我的对象内部调用一个方法。OOP JavaScript:从回调函数内部调用方法

function testObject() { 
    var self = this; 

    var functions = new Array(); 

    this.updateObject = function() { 
     console.log('updated') 
    } 

    this.addFunction = function(func) { 
     functions.push(func) 
    } 

    this.callFunctions = function() { 
     $.each(functions, function(key, value) { 
      functions[key]() 
     }) 
    } 
} 



var myobject = new testObject(); 
myobject.addFunction(
     function() { 
      $(':text').on('change', function() { 
       return self.updateObject(); 
      }) 
     } 
) 

这是我正在构建的插件的过于简化的版本。回调工作正常,但我不能使用self.updateObject();在它内部,因为它输出非法调用。

如何正确调用回调中的方法?

回答

1

问题是self超出回调函数的范围,因为该功能只有在它被定义其中的变量的作用域。该回调定义在testObject之外。

一种解决方案是在回调函数的this上下文结合使用Function.prototype.call(self)self,当你在callFunctions()调用它。然后在回调中,您可以使用this来引用testObject实例。在您的回调示例中,它包含一个jQuery事件,因此您将丢失this上下文。要纠正您可以在jQuery更改事件之前创建等于this的本地self

function testObject() { 
    var self = this; 

    var functions = new Array(); 

    this.updateObject = function() { 
     console.log('updated') 
    } 

    this.addFunction = function(func) { 
     functions.push(func) 
    } 

    this.callFunctions = function() { 
     $.each(functions, function(key, value) { 
      functions[key].call(self); // call it and bind the context to self 
     }) 
    } 
} 

var myobject = new testObject(); 
myobject.addFunction(
     function() { 
      var self = this; // needed because the change event will overwrite 'this' 
      $(':text').on('change', function() { 
       return self.updateObject(); // use self to access testObject 
      }) 
     } 
) 
myobject.callFunctions(); 

另外,您可以通过self作为参数传递给回调。要做到这一点,在.call()行更改为:

functions[key].call(null, self); 

并更改回调接受一个参数,像这样:

myobject.addFunction(
     function(self) { // self as an argument 
      $(':text').on('change', function() { 
       return self.updateObject(); // use self to refer to testObject 
      }) 
     } 
) 
+0

嗨MrCode!非常感谢您的复杂答案。不幸的是,我仍然遇到同样的错误。 Uncaught TypeError:非法调用。我曾尝试过以多种方式调用它,即使在理论上应该这样做也行不通。 –

+0

编辑。我第一次做对了。问题在于非法调用方法的updateObject()方法。感谢您的帮助 –

0
function testObject() { 
    var self = this; 

    var functions = new Array(); 

    this.updateObject = function() { 
     console.log('updated') 
    } 

    this.addFunction = function(func) { 
     functions.push(func.bind(self)) // Bind the context 
    } 

    this.callFunctions = function() { 
     $.each(functions, function(key, value) { 
      functions[key]() 
     }) 
    } 
} 

var myobject = new testObject(); 

myobject.addFunction(
     function() { 
      var self = this; 

      $(':text').on('change', function() { 
       return self.updateObject(); 
      }) 
     } 
) 

或者你可以用这个也:

myobject.addFunction(
      function() {  
       $(':text').on('change', this.updateObject); 
      } 
    )