
本文解释为何在 for 循环中直接为 radio 元素赋值 `onclick` 会导致所有按钮点击时都显示最后一个值,并提供使用 `addeventlistener` 和事件委托两种现代、可靠的解决方案。
你遇到的问题本质上是 JavaScript 闭包与变量作用域的经典陷阱。原始代码看似为每个单选按钮独立绑定了点击事件,但实际执行时,所有箭头函数共享同一个 i 变量(在循环结束后 i === radio.length),且 radio[i] 在事件触发时已越界,导致运行时错误或意外行为(如始终弹出 undefined)。
更关键的是:onclick = handler 是为每个元素单独设置事件处理器,而非“一次性触发”——只要该元素被点击,处理器就会执行。因此每次点击都会触发对应绑定的函数,这完全符合预期,问题不在于“为何多次执行”,而在于“为何总是显示错误的值”。
✅ 正确做法一:使用 let 声明 + addEventListener
let 在每次循环迭代中创建块级作用域,确保每个回调函数捕获当前轮次的 radio[i]:
const radio = document.getElementsByName('subject');
for (let i = 0; i < radio.length; i++) {
radio[i].addEventListener('click', () => {
alert(`You chose ${radio[i].value}.`);
});
}✅ 优势:语义清晰、支持多个监听器、错误可捕获、兼容性好(IE9+)。
⚠️ 注意:若后续需移除监听器,应保存函数引用:
for (let i = 0; i < radio.length; i++) {
const handler = () => alert(`You chose ${radio[i].value}.`);
radio[i].addEventListener('click', handler);
// 后续可调用 radio[i].removeEventListener('click', handler)
}✅ 正确做法二:事件委托(推荐用于动态内容)
将监听器统一绑定到父容器(如










