[英]setTimeout Illegal invocation TypeError: Illegal invocation
Illegal invocation TypeError: Illegal invocation
is thrown when calling setTimeout
with a variable callback. Illegal invocation TypeError: Illegal invocation
使用变量回调调用setTimeout
,引发Illegal invocation TypeError: Illegal invocation
。 I read that this happens when this
refers to another object in the callback and that bind
or arrow functions are used to solve this. 我读到,当
this
引用回调中的另一个对象并且使用bind
或arrow函数来解决此问题时,就会发生这种情况。 However, no this
in my callback. 但是,在我的回调中没有
this
。
The code is as follows: 代码如下:
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');
Note that I use babel and es2015. 请注意,我使用babel和es2015。
In the sample code, functions setTimeout and clearTimeout are being invoked with an invalid context ( this
). 在示例代码中,使用无效上下文(
this
)调用了setTimeout和clearTimeout函数。 On possible fix is binding to the correct context ( window
): 可能的解决方法是绑定到正确的上下文(
window
):
constructor(callback) {
this._alarms = {};
this.setTimeout = window.setTimeout.bind(window);
this.clearTimeout = window.clearTimeout.bind(window);
this._callback = callback || function () {};
}
It is usual to think of the this
object inside a function pointing to the object to the left of the dot in the invocation: 通常会在函数中想到
this
对象,该函数指向调用中点左侧的对象:
alerts.create(...) // inside create(), this === alerts
^
|___ "this"
When there's no dot, it depends whether the caller function is strict: 如果没有点,则取决于调用者函数是否严格:
var create = alerts.create
create() // this === Window or global
^
|_____ no dot
And 和
'use strict'
var create = alerts.create
create() // this === undefined
^
|_____ no dot
Given we call setTimeout
without a dot, we may think that the this
context doesn't matter. 给定我们调用不带点的
setTimeout
,我们可能认为this
上下文无关紧要。 But in browsers it will complain if you call it with a dot, or use a variant that pass as context something different than window. 但是在浏览器中,如果您使用圆点来调用它,或者使用的变体作为上下文传递的变量与窗口不同,它将发出抱怨。
Firefox: 火狐:
Uncaught TypeError: Illegal invocation
未捕获的TypeError:非法调用
Chrome: 铬:
TypeError: 'setTimeout' called on an object that does not implement interface Window.
TypeError:'setTimeout'在未实现接口Window的对象上调用。
Others suggested sticking to the usual setTimeout(fn, timeout)
. 其他人建议坚持通常的
setTimeout(fn, timeout)
。 Yet another way is creating an anonymous function: 还有一种方法是创建一个匿名函数:
this.setTimeout = (fn, timeout) => setTimeout(fn, timeout);
There is no this
in your callback, however setTimeout
is called globally. 您的回调中没有
this
函数,但是setTimeout
被全局调用。
So this.setTimeout
should be setTimeout
所以
this.setTimeout
应该是setTimeout
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 = setTimeout(this._callback, when - Date.now(), this._alarms[alarmName]); } } let alarms = new AlarmService(function (alarm) { console.log('Alarm', alarm); }); alarms.create('alarmName', Date.now() + 3000, 'Title', 'Message'); // Exception is thrown here
I got this error because I passed the wanted context
to setTimeout
instead of its callback
我收到此错误是因为我将
wanted context
传递给setTimeout
而不是its callback
this the wrong code, where I pass this
to setTimeout
这种错误的代码,在那里我通过
this
来setTimeout
setTimeout.call(this, function () {
// this.model.starIcon = "fa-star";
this._toggleStarIcon()
}, 150);
I correct way to pass you context is to pass it to setTimeout callback
我正确的传递上下文的方法是将其传递给
setTimeout callback
I used $.proxy
to do that 我用
$.proxy
来做到这一点
here is the correct code 这是正确的代码
setTimeout($.proxy(function () {
// this.model.starIcon = "fa-star";
this._toggleStarIcon()
}, this), 150);
hope this helps you 希望这对您有帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.