伙计 - 我试图学习如何编写OO Javascript,我来自as3 OO背景...... 我正在通过一个课程'方法作为对另一个类的回调......
在下面的示例中,我创建了一个AppController类的实例,在其中,我创建了一个ConnectionMonitor类的实例。我传递一个AppController方法,由ConnectionMonitor调用。回调工作正常,但似乎回调函数中的内容失去了它的范围(AppController)...
有什么想法吗?
//in the HTML
<script>
$(document).ready( function(){
new AppContoller().init();
});
</script>
//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());
}
答案 0 :(得分:4)
修改init
以将回调绑定到原始上下文:
this.init = function() {
this.connection.detectInitialConnection(
this.initialConnectionDetected.bind(this));
}
不幸的是,bind
is not supported in all browsers,但您可以在闭包中捕获this
的当前值以实现类似的效果:
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);
}
每个示例中的要点是保留对this
被调用的上下文中detectInitialConnection
的值的引用。
答案 1 :(得分:2)
setTimeout将运行绑定到window
的传递函数。您可以使用ES5 bind
:
this.connection.detectInitialConnection( this.initialConnectionDetected.bind(this) );
这在旧版浏览器中不起作用,但提供的MDN链接有解决方法。
答案 2 :(得分:2)
这在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");
}
}
答案 3 :(得分:1)
this.initialConnectionDetected
将传递该函数,但没有它应该在实例上执行的信息。
调用this.foo()
将传递此信息,但仅在直接调用时,而不是在传递并稍后调用时(这就是您正在执行的操作)。
您必须使用以下方法绑定此信息(即this
值,即实例)。 .bind
:
this.connection.detectInitialConnection(this.initialConnectionDetected.bind(this));
请注意,.bind
在旧版浏览器中不可用,但有可用的填充程序可以模仿它的行为。
答案 4 :(得分:1)
其他答案都是正确的,但似乎没有人提到Function.prototype.bind
是not supported in all browsers。要使其有效,您需要添加Kris Kowal's es5-shim library。