如何向高阶函数传递带参数的函数?JS按钮音效实现疑问
解决按钮点击事件传参问题
你说得没错,setPathAndPlay(currentButton)这种写法会立即执行函数,而不是把它作为点击事件的回调函数传递给监听器——事件监听器需要接收的是一个函数引用,而不是函数执行后的结果。下面给你几个简单易懂的解决方案:
方案1:箭头函数包装(最简洁)
用箭头函数把目标函数包起来,点击事件触发时才会调用setPathAndPlay并传递参数:
function setPathAndPlay(currentButton) { let audioPath; switch (currentButton.innerHTML) { case "w": { audioPath = "./sounds/crash.mp3"; break; } // 补充其他按钮的case } if (audioPath) { // 防止没有匹配到case时创建无效Audio对象 const audio = new Audio(audioPath); audio.play(); } } for (let currentButton of drumArray) { currentButton.addEventListener("click", () => setPathAndPlay(currentButton)) }
因为循环里用了let(块级作用域),每个按钮对应的currentButton都是独立的,不会出现变量覆盖问题。
方案2:利用事件处理函数的this(更优雅)
其实事件处理函数本身可以通过this获取到触发点击的按钮元素,这样连参数都不用传了,直接修改函数:
function setPathAndPlay() { // this 就是当前被点击的按钮DOM元素 let audioPath; switch (this.innerHTML) { case "w": audioPath = "./sounds/crash.mp3"; break; // 补充其他按钮的case } if (audioPath) { const audio = new Audio(audioPath); audio.play(); } } for (let currentButton of drumArray) { // 直接传递函数引用即可,不用包装 currentButton.addEventListener("click", setPathAndPlay) }
这个方案更简洁,也符合事件处理的常规写法,推荐优先使用。
方案3:普通匿名函数包装(和内联写法逻辑一致)
如果你更习惯普通函数的写法,也可以用匿名函数包裹:
for (let currentButton of drumArray) { currentButton.addEventListener("click", function() { setPathAndPlay(currentButton); }) }
效果和箭头函数完全一样,只是写法不同。
内容的提问来源于stack exchange,提问作者713sean
相关产品推荐
相关产品推荐

