0

the following code gives me a Uncaught TypeError: Illegal invocation:

document.querySelector("h1").addEventListener('click', function(evt) {
  setTimeout(this.classList.add, 2000, "bold-h1");
});

But what's wrong with it? Wouldn't that be the same as if I would write

document.querySelector("h1").addEventListener('click', function(evt) {
  setTimeout(() => { this.classList.add("bold-h1"); }, 2000);
});

? (the latter works by the way)

Andreas Utzinger
  • 392
  • 2
  • 12

1 Answers1

3

Functions invoked by setTimeout are executed as global code. The add method is expected to be called on a classList object (i.e. its this will be a classList object), but in the case of global code its this will be the global object or undefined in strict mode.

The global object doesn't have a classList property so this.classList returns null, and calling any method (or even attempting to access any property) of null throws an error.

The reason that the second case works is that the function passed as the listener wraps the arrow function. An arrow function's this is bound to the this of its enclosing execution context, so the arrow function's this is the this of the listener, which is the element the listener is on. So now when the anonymous function is called by setTimeout, its this is the element and this.classList.add(...) works.

RobG
  • 142,382
  • 31
  • 172
  • 209