2017-12-02 19 views
0

Illegal invocation TypeError: Illegal invocationは、可変コールバックでsetTimeoutを呼び出すとスローされます。これは、thisがコールバック内の別のオブジェクトを参照し、bindまたは矢印関数がこれを解決するために使用されている場合に発生することがあります。ただし、私のコールバックにはthisはありません。次のようにsetTimeout不正な呼び出しTypeError:不正な呼び出し

コードは次のとおりです。私はバベルとes2015を使用

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');

注意。

+2

機能であるあなたがあなた自身のオブジェクトへのそれへの参照をコピーしたため、エラーを投げ、その後、あなたは 'このよう独自のオブジェクトでそれを呼び出しています'文脈。コールバックが 'this'を参照していないことに違いはありません。問題は 'window.setTimeout()'の代わりに 'this.setTimeout()'を呼び出すことです。 – Pointy

答えて

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コンテキストは関係ないと思うことがあります。しかし、ブラウザではドットで呼び出すと文句を言いますが、ウィンドウとは別のものとしてコンテキストとして渡すバリアントを使用します。

のFirefox:

Uncaught TypeError: Illegal invocation

Chromeは:

TypeError: 'setTimeout' called on an object that does not implement interface Window.


その他は通常のsetTimeout(fn, timeout)にこだわる提案しました。 は、さらにもう1つの方法は、匿名関数を作成します

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

を使用するか、この逆テンシャーコードなしでsetTimeoutおよびclearTimeoutを使用してください –

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

でなければなりません。

関連する問題