使用变量回调调用 setTimeout
时,会抛出
非法调用 TypeError: Illegal inspiration
。我读到,当 this
引用回调中的另一个对象时会发生这种情况,并且使用 bind
或箭头函数来解决此问题。但是,我的回调中没有 this
。
代码如下:
class AlarmService {
constructor(callback) {
this._alarms = {};
this.setTimeout = window.setTimeout;
this.clearTimeout = window.clearTimeout;
this._callback = callback || function () {};
}
create(alarmName, when, title, message) {
this._alarms[alarmName] = {
'title': title,
'message': message
};
this._alarms.timeout = this.setTimeout(this._callback, when - Date.now(),
this._alarms[alarmName]);
}
}
let alarms = new AlarmService(function (alarm) {
console.log('Alarm', alarm.name);
});
// Exception is thrown here
alarms.create('alarmName', Date.now() + 3000, 'Title', 'Message');
请注意,我使用 babel 和 es2015。
最佳答案
在示例代码中,函数 setTimeout 和clearTimeout 是使用无效上下文 (this
) 调用的。可能的解决方法是绑定(bind)到正确的上下文(窗口
):
constructor(callback) {
this._alarms = {};
this.setTimeout = window.setTimeout.bind(window);
this.clearTimeout = window.clearTimeout.bind(window);
this._callback = callback || function () {};
}
通常认为函数内的 this
对象指向调用中点左侧的对象:
alerts.create(...) // inside create(), this === alerts
^
|___ "this"
当没有点时,取决于调用者函数是否严格:
var create = alerts.create
create() // this === Window or global
^
|_____ no dot
还有
'use strict'
var create = alerts.create
create() // this === undefined
^
|_____ no dot
假设我们调用不带点的 setTimeout
,我们可能会认为 this
上下文并不重要。但在浏览器中,如果您用点调用它,或者使用与窗口不同的上下文作为上下文传递的变体,它会提示。
火狐浏览器:
Uncaught TypeError: Illegal invocation
Chrome:
TypeError: 'setTimeout' called on an object that does not implement interface Window.
其他人建议坚持使用通常的setTimeout(fn, timeout)
。
另一种方法是创建匿名函数:
this.setTimeout = (fn, timeout) => setTimeout(fn, timeout);
关于javascript - setTimeout 非法调用 TypeError : Illegal invocation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47608666/