进行OO javascript回调时的范围

伙计们 – 我正在努力学习如何编写OO Javascript,我来自as3 OO背景……我遇到的问题是将一个类’方法作为回调传递给另一个类…

在下面的示例中,我创建了一个AppController类的实例,在其中,我创建了一个ConnectionMonitor类的实例。 我传递一个AppController的方法,由ConnectionMonitor调用。 回调工作正常,但似乎回调函数内部的内容失去了它的范围(AppController)……

有什么想法吗?

//in the HTML  $(document).ready( function(){ new AppContoller().init(); });  //in the js file //AppController Class var AppContoller = function(){ this.body = $("body"); this.init = function(){ this.connection = new ConnectionMonitor(); this.connection.detectInitialConnection( this.initialConnectionDetected ); } //callback function I pass this.initialConnectionDetected = function(bool){ if(bool){ trace("app connected? "+bool); // logs - "app connected? true" this.showOnlineSwf(); //thows error - "Object [object DOMWindow] has no method 'showOnline' " } else{ } } this.showOnlineSwf = function(){ trace("i'm online"); } } //ConnectionMonitor Class var ConnectionMonitor = function() { this.detectInitialConnection = function(callbackFunction){ setTimeout(callbackFunction, 1000, [true]); } } function trace(arg){ console.log(arg.toString()); } 

setTimeout将运行绑定到window的传递函数。 您可以使用ES5的bind覆盖它:

 this.connection.detectInitialConnection( this.initialConnectionDetected.bind(this) ); 

这在旧版浏览器中不起作用,但提供的MDN链接有一个解决方法。

修改init以将回调绑定到原始上下文:

 this.init = function() { this.connection.detectInitialConnection( this.initialConnectionDetected.bind(this)); } 

遗憾的是, 并非所有浏览器都支持bind ,但您可以在闭包中捕获此的当前值以实现类似的效果:

 this.init = function() { var that = this; this.connection.detectInitialConnection(function(detected) { that.initialConnectionDetected(detected); }); } 

另一种方法是使detectInitialConnection能够处理可选的上下文参数:

 this.detectInitialConnection = function(callbackFunction, _this){ setTimeout(function() { callbackFunction.apply(_this || this, arguments); }, 1000, [true]); } 

然后你会这样称呼它:

 this.init = function() { this.connection.detectInitialConnection( this.initialConnectionDetected, this); } 

这些示例中的每一个中的要点是从调用detectInitialConnection的上下文中保留对this的值的引用。

这在javascript中很棘手,特别是因为它与构造函数和传递函数有关。 如果你这样做,它将工作:

 //AppController Class var AppContoller = function(){ this.body = $("body"); var self = this; this.init = function(){ this.connection = new ConnectionMonitor(); this.connection.detectInitialConnection( this.initialConnectionDetected ); } //callback function I pass this.initialConnectionDetected = function(bool){ if(bool){ trace("app connected? "+bool); // logs - "app connected? true" self.showOnlineSwf(); } else{ } } this.showOnlineSwf = function(){ trace("i'm online"); } } 

其他答案是正确的,但似乎没有人提到所有浏览器都不支持 Function.prototype.bind 。 为了使它成功,你需要包括Kris Kowal的es5-shim库 。

this.initialConnectionDetected将传递函数,但没有应该在实例上执行的信息。

调用this.foo()将传递此信息,但仅在直接调用时,而不是在传递并稍后调用时(这是您正在执行的操作)。

您必须使用例如.bind绑定此信息(即this值,即实例):

 this.connection.detectInitialConnection(this.initialConnectionDetected.bind(this)); 

请注意, .bind在旧版浏览器中不可用,但有可用的填充程序可以模仿它的行为。