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

Decoupling when using anonymous functions in third party javascript (FB)

本文关键字:函数 解耦 JavaScript 第三方 FB      更新时间:2023-09-26

我正在使用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 中,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 变量的作用域的闭包)用于使用正确的上下文调用您的函数。有关闭包的更多信息,请点击此处:闭包并不复杂 有关this的更多信息: 你必须记住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 。我们的所有其他功能都是真正私密的。(我还冒昧地确保函数具有名称,因为这有助于您的工具为您提供帮助。

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