所以,我有这个:
var listener = {
_handleMessage: function(b) {
var c = b.data;
if (c) this.{c}; //this not works
},
testFunc: function() {
console.log("success");
}
startListen: function() {
window.addEventListener("message", this._handleMessage, !1)
}
};
listener.startListen();
预期结果:当数据通过startListen
时,它会将数据传递给_handleMessage
。从那里,它检查数据以调用监听器内的函数(例如,如果testFunc
是b.data
,则将调用testFunc
)。
使用像我发布的内容不起作用。使用this[c]();
无效(this[c] is not a function)
。还有其他解决方案吗?
解决
找到一种更优雅的方式:
_handleMessage: function(b) {
var c = b.data;
if (c) {
var d = listener[c.action];
d && "function" == typeof d (function() {
d.call(listener, c.params || {});
});
}
},
答案 0 :(得分:2)
你在哪里:
window.addEventListener("message", this._handleMessage, !1);
将 _handleMessage 函数传递给元素处理程序。当处理程序调用时,它的 this 被设置为其处理程序调用函数的元素,而不是 listener 对象。您可以按照StriplingWarrior的说明修复它,或者您可以执行以下操作:
window.addEventListener("message", function(){listener._handleMessage()}, false)
以便将 _handleMessage 中的 设置为您期望的对象(即 listener )。
在“已解决”的代码中:
d && "function" == typeof d (function() {
d.call(listener, c.params || {});
});
只要 d 解析为真值,那么分组运算符中的函数始终评估,typeof d
返回的内容无关紧要,所以你有效地拥有:
d && d.call(listener, c.params || {});
这样:
if (c) {
var d = listener[c.action];
d && "function" == typeof d (function() {
d.call(listener, c.params || {});
});
}
也可能是:
if (c && listener[c.action]) {
listener[c.action](c.params || {});
}
答案 1 :(得分:1)
这已被多次询问和回答。您需要指定this._handleMessage.bind(this)
,以便_handleMessage
具有上下文(this
)。虽然有些人可能会说使用function(b) { self._handleMessage(b); })
作为其他答案,但这可能更为简洁。
精确相同的逻辑适用于您将类方法作为回调传递的任何情况,例如setTimeout
。
以上是最简单的,但还有其他方法。如果您需要在多个位置使用_handleMessage
的绑定版本,则预绑定它可能很有用:
listener._handleMessage = listener._handleMessage.bind(listener);
或者,你可以使用下划线的_.bindAll
:
_.bindAll(listener, '_handleMessage');
或者,您可以在对象内的init
函数中执行此操作:
var listener = {
_handleMessage: function(b) {
var c = b.data;
if (c) this.{c}; //this not works
},
startListen: function() {
window.addEventListener("message", this._handleMessage, !1)
},
init: function() {
this._handleMessage = this._handleMessage.bind(this);
return this;
}
}.init();
如果您在ES6环境中工作,胖箭头功能可以通过defining this
lexically解决此问题,所以您可以这样做
window.addEventListener("message", b => this._handleMessage(b), !1);
在这种情况下,this
不是事件机制(通常是全局对象)调用函数的上下文的值,而是周围的this
,这是什么你想要的。
至于this.{c}
,不知道你在那里做什么。
答案 2 :(得分:0)
请记住,JavaScript中的this
是指在运行时调用该函数的上下文。当“message”事件触发时,您的listener
对象的上下文中不会调用您的事件侦听器。
尝试创建一个匿名函数作为处理程序,并确保它在正确的上下文中调用事件,如下所示:
var listener = {
_handleMessage: function(b) {
var c = b.data;
if (c) this.{c}; //this not works
},
testFunc: function() {
console.log("success");
}
startListen: function() {
var t = this; // capture "this" when `listener.startListen()` is invoked.
window.addEventListener("message", function(b) {t._handleMessage(b);}, !1)
}
};
listener.startListen();