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

时间:2011-05-12 11:33:38

标签: javascript oop facebook

我正在使用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',显然我不想开始编写对具体版本Controller的引用!

我猜我错误地传递了这个函数?

感谢。

1 个答案:

答案 0 :(得分:3)

在JavaScript中,this完全由如何调用函数定义,而不是定义它的位置。这与其他一些语言不同。 (JavaScript没有方法,它只是有一些函数和一些语法糖,有时候它们看起来像方法。)所以尽管你正确地传递了你的函数,Facebook却不知道你的对象实例,在调用函数时无法正确设置this

检查FB.Event.subscribe文档以查看它是否提供了一种说明用于调用事件处理函数的“上下文”的方法。它可能提供了一种方法。 (这通常是contextthisArg参数。)

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

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变量的作用域的闭包)使用正确的上下文调用您的函数。有关此处闭包的更多信息:Closures are not complicated有关this的更多信息,请访问You must remember this

但是,您是否真的会有Controller的多个实例?从基于类的语言转向JavaScript的人倾向于不必要地使用构造函数(粗略的“类”模拟)。如果你需要有一个以上的对象实例,那么它们是正确的选择,但是如果你在页面上只有一个Controller对象,那么使用构造函数并摆弄它this有点矫枉过正。

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

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。上面的controllerObject只有一个属性,即函数go。我们所有的其他功能都是真正私密的。 (我也冒昧地确保函数具有名称,因为helps your tools help you。)

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