"Uncaught TypeError: Illegal invocation" when I add a class from setTimeout

"Uncaught TypeError: Illegal invocation" when I add a class from setTimeout

下面的代码给我一个 Uncaught TypeError: Illegal invocation:

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

但这有什么问题呢?那不是和我写的一样吗

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

? (后者顺便工作)

setTimeout 调用的函数作为全局代码执行。 add 方法预计将在 classList 对象上调用(即它的 this 将是 classList 对象),但在全局代码的情况下,它的 this 将是全局对象或在严格模式下未定义。

全局对象没有 classList 属性 所以 this.classList returns null,调用 null 的任何方法(甚至尝试访问任何 属性)都会引发错误。

第二种情况有效的原因是作为监听器传递的函数包装了箭头函数。箭头函数的 this 绑定到其封闭执行上下文的 this,因此箭头函数的 this是监听器的this,也就是监听器所在的元素。所以现在当匿名函数被 setTimeout 调用时,它的 this 是元素并且 this.classList.add(...) 有效。