使用对象解构调用ev.preventDefault()触发Illegal invocation错误原因咨询
为什么解构
preventDefault会触发"Illegal invocation"错误? 这个坑我之前踩过!核心问题出在JavaScript里方法的this绑定机制上。
咱们先理清楚两种调用方式的区别:
当你直接写ev.preventDefault()的时候,这个方法里的this是自动指向ev这个事件对象的——毕竟preventDefault是ev的一个方法,它内部需要访问事件对象的状态才能完成阻止默认行为的操作。
但如果你用对象解构把preventDefault单独拎出来,就相当于把这个函数从它所属的事件对象上"拆"下来了。此时再直接调用preventDefault(),在浏览器的严格模式环境下(事件处理函数默认开启严格模式),这个函数的this会变成undefined。而preventDefault必须依赖事件对象作为this才能正常运行,浏览器检测到这种非法的调用场景,就会抛出"Uncaught TypeError: Illegal invocation"错误。
给你看个直观的代码对比:
正常工作的写法
const button = document.getElementById(`test-button`); button.onclick = (ev) => { ev.preventDefault(); // 这里的this指向ev,一切正常 };
触发错误的解构写法
const button = document.getElementById(`test-button`); button.onclick = ({ preventDefault }) => { preventDefault(); // 这里的this是undefined,触发错误 };
解决办法
有几种方式可以修复这个问题:
- 最直接的:放弃解构,直接用事件对象调用方法
这也是最常用的写法,简单直观,完全不会有绑定问题。 - 手动绑定this到事件对象
如果非要用解构,可以用call()或者bind()强制把this绑定回原事件对象:button.onclick = (ev) => { const { preventDefault } = ev; preventDefault.call(ev); // 强制让this指向ev }; - 用bind提前绑定上下文
也可以先给解构出来的方法绑定好this再调用:button.onclick = (ev) => { const { preventDefault } = ev; const boundPreventDefault = preventDefault.bind(ev); boundPreventDefault(); };
内容的提问来源于stack exchange,提问作者dwhieb
相关产品推荐
相关产品推荐

