javascript - setTimeout 非法调用 TypeError : Illegal invocation

标签 javascript ecmascript-6

使用变量回调调用 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/

相关文章:

javascript - 当 Mocha 测试失败时,它会将一个对象记录到控制台

javascript - 从 ionic Controller 访问 Cordova 插件

javascript - 了解 .reduce() 中的许多函数参数

javascript - JS对象解构不定义变量名

javascript - onPress 方法中箭头函数与普通函数的行为

javascript - 找到下一个元素,但不是为了具有相同的类

javascript - 居中页脚内容

javascript - 将变量传递给 jQuery 函数

ecmascript-6 - 如何为 Polymer 2 创建自定义元素 "resize"mixin?

javascript - 当其中的变量更新时,es6 字符串模板是否更新