在第三方javascript(FB)中使用匿名函数时的解耦

在第三方javascript(FB)中使用匿名函数时的解耦,javascript,oop,facebook,Javascript,Oop,Facebook,我使用FB.Event.subscribe()观察者模型来确定用户何时登录。此方法接受两个参数,一个包含要监视的内容的字符串和回调函数 我正在跟踪几个以相同方式处理事件的事件,因此我将回调函数设置为预定义方法,并将其传递给FB.event.subscribe(),如下所示: Controller.prototype.go = function() { FB.Event.subscribe('auth.login', this.fbHandleStatusChange); FB.E

我使用FB.Event.subscribe()观察者模型来确定用户何时登录。此方法接受两个参数,一个包含要监视的内容的字符串和回调函数

我正在跟踪几个以相同方式处理事件的事件,因此我将回调函数设置为预定义方法,并将其传递给FB.event.subscribe(),如下所示:

Controller.prototype.go = function() {
    FB.Event.subscribe('auth.login', this.fbHandleStatusChange);
    FB.Event.subscribe('auth.logout', this.fbHandleStatusChange);
}

Controller.prototype.fbHandleStatusChange = function(response) {
    // Doesn't work
    this.otherFunction();
}

Controller.prototype.otherFunction = function() {
    alert('hello');
}
不幸的是,这意味着我在fbHandleStatusChange的范围内失去了对“this”的访问,显然我不想开始编写对控制器具体版本的引用

我猜我传递的函数不正确


谢谢。

在JavaScript中,
这个
完全由函数的调用方式来定义,而不是定义在什么地方。这与其他一些语言不同。(JavaScript没有方法,它只有函数和一些语法糖,使它们有时看起来像方法。)因此,尽管您正确地传递了函数,Facebook不知道您的对象实例,在调用函数时无法正确设置

检查
FB.Event.subscribe
文档,看看它是否提供了一种方式来说明使用什么“上下文”来调用事件处理程序函数。它可能提供了一种实现这一点的方法。(这通常是一个
上下文
thisArg
参数。)

如果没有,您可以通过关闭来轻松解决问题:

Controller.prototype.go = function() {
    var self = this;

    FB.Event.subscribe('auth.login', handleChange);
    FB.Event.subscribe('auth.logout', handleChange);
    function handleChange() {
        return self.fbHandleStatusChange();
    }
}
它将
this
的副本抓取到名为
self
的变量中,该变量由
handleChange
函数(包含
self
变量的作用域上的闭包)使用,以正确的上下文调用函数。有关闭包的更多信息,请参见此处:有关
的更多信息:

不过,您是否真的要有多个
控制器的实例?从基于类的语言学习JavaScript的人倾向于不必要地使用构造函数(粗略的“类”模拟)。如果您需要一个对象的多个实例,那么它们是正确的选择,但是如果您在页面上只需要一个
控制器
对象,那么使用构造函数和摆弄
这个
就太过分了

如果您不需要多个独立的
控制器
实例,那么:

var controllerObject = (function() {
    var inst = {};

    inst.go = go; // Make `go` a publicly-accessible function of the object
    function go() {
        FB.Event.subscribe('auth.login', fbHandleStatusChange);
        FB.Event.subscribe('auth.logout', fbHandleStatusChange);
    }

    // This is private to us, so we don't expose it as a property on the object
    function fbHandleStatusChange(response) {
        // Doesn't work
        otherFunction();
    }

    // This is also private to us
    function otherFunction() {
        alert('hello');
    }

    return inst;
})();
它通过外部匿名函数创建一个私有作用域,并在该作用域内创建一个实例(
inst
),然后返回该实例并将其称为
controllerObject
)<代码>控制器对象
在上述中只有一个属性,即函数
go
。我们所有的其他功能都是真正的私人功能。(我还冒昧地确保函数有名称,因为这样做。)


请注意,我们实际上并没有在函数调用中的任何地方引用
inst
,因为它们都是闭包范围的局部。我们甚至可以通过在外部闭包中包含其他
var
s来拥有私有数据。

为了向其他读者澄清,在原型中定义:var self=this。go@Steve:很抱歉,我只是在添加解释时注意到了这一点。:-)很高兴这帮了忙(幸亏找到了遗漏的部分)。回复:新实例。我正在开发其他人的代码,他们使用的是MVC框架,所以我不能这样放肆。这是一个很好的观点,我使用全局变量作为解决方案,然后突然我的OOP意识开始了。匿名包装器可能是一个很好的折衷方案,但由于它的代码基础是什么,我认为它会增加额外的工作来解决一些问题。再次感谢您的深入反馈!我们一定要尽快全面阅读这些文章。@Steve::-)只是介绍其他选择,是否正确取决于具体情况。