setTimeout非法调用TypeError:非法调用

时间:2017-12-02 14:00:27

标签: javascript ecmascript-6

使用变量回调调用Illegal invocation TypeError: Illegal invocation时抛出

setTimeout。我读到当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。

3 个答案:

答案 0 :(得分:2)

在示例代码中,使用无效的上下文(this)调用函数setTimeout和clearTimeout。可能的修复是绑定到正确的上下文(window):

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背景并不重要。但是在浏览器中,如果你用点来调用它,或者使用一个作为上下文而不是窗口传递的变体,它会抱怨。

火狐:

  

未捕获的TypeError:非法调用

铬:

  

TypeError:' setTimeout'调用了一个没有实现接口Window的对象。

其他人建议坚持通常setTimeout(fn, timeout)。 另一种方法是创建一个匿名函数:

this.setTimeout = (fn, timeout) => setTimeout(fn, timeout);

答案 1 :(得分:1)

回调中没有this,但全局调用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



我还更改了你的日志行,因为你的闹钟没有名字。

答案 2 :(得分:0)

我收到此错误是因为我将wanted context而不是setTimeout传递给了its callback

这是错误的代码,我在其中将this传递给setTimeout

setTimeout.call(this, function () {
    // this.model.starIcon = "fa-star";
    this._toggleStarIcon()
}, 150);

传递上下文的正确方法是将其传递给setTimeout callback

我用$.proxy做到了

这是正确的代码

setTimeout($.proxy(function () {
    // this.model.starIcon = "fa-star";
    this._toggleStarIcon()
}, this), 150);

希望这对您有帮助

相关问题