如何向EventListener传递for循环中的动态索引参数i
问题原因
你当前代码无法正常运行的核心原因:
- 事件绑定传入的回调函数,默认接收的第一个参数是浏览器传递的事件对象(Event),不会自动传入for循环的索引值。你当前回调里形参命名为
i,实际拿到的是鼠标事件对象,自然无法读取对应数组的内容。 - 直接把函数名作为回调传入的写法,无法附带传递自定义的索引参数,需要做一层中转处理。
可行实现方案
方案1:匿名函数包装(最简洁,适配你当前的let循环写法)
你当前循环用let声明索引i,本身就会为每次迭代生成独立的块级作用域变量,不会出现所有回调都拿到最终索引的闭包问题,只需要在绑定事件时用匿名箭头函数包一层,把当前迭代的i传入目标回调即可:
function roleDescription() { // вторая ступень = описание роли при наведении, выбор роли при клике for (let i = 0; i < originDescription.length; i++) { // 包装一层,把当前迭代的i传入对应处理函数 buttons[i].addEventListener('mouseover', () => asignDesc(i)); // 如果后续需要用到事件对象,可以写成 (e) => asignRole(i, e),同步调整回调的形参顺序即可 buttons[i].addEventListener('click', () => asignRole(i), { once: true }); } }
这种写法不需要修改你已经写好的asignRole、asignDesc函数逻辑,直接改绑定部分就能正常运行。
方案2:DOM自定义属性存索引(不需要依赖循环变量作用域)
如果不想用闭包传参,可以把索引直接存在对应按钮元素的自定义data属性上,回调触发时从事件绑定的元素上读取索引:
首先修改事件绑定逻辑,给每个按钮存入索引:
function roleDescription() { for (let i = 0; i < originDescription.length; i++) { // 把索引存在按钮的data-index属性上 buttons[i].dataset.index = i; buttons[i].addEventListener('mouseover', asignDesc); buttons[i].addEventListener('click', asignRole, { once: true }); } }
然后修改两个回调函数,从事件对象中读取索引:
function asignRole(e) { // 用currentTarget确保取到绑定事件的按钮元素,避免点击内部子元素时拿错 const i = Number(e.currentTarget.dataset.index); playerrole = role[i]; alert(playerrole); makeSpecial(); } function asignDesc(e) { const i = Number(e.currentTarget.dataset.index); maintext.textContent = originDescription[i]; maintext.style.fontSize = '15px'; }
注意事项
不要为了省事把循环里的let改成var,var没有块级作用域,会导致所有回调都拿到循环结束后的最终索引值,所有按钮触发时都会取到最后一项的数据。
内容的提问来源于stack exchange,提问作者Prains
相关产品推荐
相关产品推荐

