JavaScript PubSub模式:"这个"的上下文发生了什么,它为什么会丢失?

时间:2015-05-26 21:03:53

标签: javascript publish-subscribe

我开始尝试使用JavaScript中的发布/订阅模式,但现在面临一个我不明白的问题。

采取以下方案:

点击按钮,会发出一条消息,这是有效的。

document.getElementById('myBtn').addEventListener('click', function() {
    PubSub.publish('topic', data);
});

在我的应用程序的另一部分中,我收到了这条消息:

function MyObj() {
    this.eventLog = [];
    var token = PubSub.subscribe('topic', this.logger);
};

MyObj.prototype.logger = function(message, data) {
    this.eventLog.push(data);
}

这里我想将已发布的数据存储在eventLog对象的MyObj属性中。不幸的是,这不起作用:

Uncaught TypeError: Cannot read property 'eventLog' of undefined

所以看起来this的上下文丢失了 - 当我console.log(this)时,会记录window对象。

我知道this对初学者来说可能很棘手,但直到现在我总能理解发生了什么,但这让我完全不解。当然MyObj会在邮件发布之前初始化,所以我在这里看不到任何问题。请有人向我解释一下这里发生了什么?

2 个答案:

答案 0 :(得分:5)

使用Function.prototype.bind

 PubSub.subscribe('topic', this.logger.bind(this))

答案 1 :(得分:0)

澄清/解释观察到的行为 - JavaScript使用词法作用域,因此 this 关键字绑定到使用的最内部范围。根据关键字的位置(函数和/或对象的功能和父级),是另一个对象。

如果您在this.eventLog中调用MyObj,则指的是MyObj。但在部分

MyObj.prototype.logger = function(message, data) {
    this.eventLog.push(data);
}

关键字在window对象的范围中被称为(父级是窗口对象),这就是您在打印时看到它的原因MyObj

从技术上讲, this 的上下文始终被推送/保存在堆栈中,因此上下文不会丢失,但会从堆栈中弹出/检索当前上下文目前的范围。

本文Quirksmode - The this keyword中描述了这种行为(在视觉上)。 在this SO post中也可以找到一些很好的例子。