我开始尝试使用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
会在邮件发布之前初始化,所以我在这里看不到任何问题。请有人向我解释一下这里发生了什么?
答案 0 :(得分:5)
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中也可以找到一些很好的例子。