为何为多元素添加addEventListener时出现Uncaught TypeError错误?
问题分析与解决
错误原因
报错Uncaught TypeError: Cannot read properties of undefined (reading 'addEventListener')的直接原因是循环边界错误:
btn = document.querySelectorAll("button")获取到4个按钮,长度len=4,数组索引范围为0-3- 你的循环条件写为
i <= len,当i=4时,btn[4]不存在(值为undefined),无法调用addEventListener方法
修复后的代码
方案1:修正循环边界
把循环条件从i <= len改为i < len即可解决:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Change Style</title> <style> button { color: rgb(255, 255, 255); background-color: rgb(255, 0, 0); border-radius: 10px; border: none; margin: 10px; padding: 15px; font-size: 20px; } button:hover { color: rgb(255, 0, 0); background: rgb(255, 255, 255); border: 3px solid black; transition: all ease-in-out 0.2s; overflow: hidden; cursor: pointer; } </style> </head> <body> <h1>You didn't click any button.</h1> <button>Button 1</button> <button>Button 2</button> <button>Button 3</button> <button>Button 4</button> <script> var heading = document.querySelector("h1"); const btn = document.querySelectorAll("button"); var len = btn.length; // 修正循环条件为i < len for (var i = 0; i < len; i++) { btn[i].addEventListener("click", func); function func() { var txt = this.innerHTML; heading.innerHTML = txt + " is clicked."; } } </script> </body> </html>
方案2:使用forEach简化代码(更推荐)
querySelectorAll返回的NodeList支持forEach方法,无需手动写for循环,代码更简洁且不易出错:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Change Style</title> <style> button { color: rgb(255, 255, 255); background-color: rgb(255, 0, 0); border-radius: 10px; border: none; margin: 10px; padding: 15px; font-size: 20px; } button:hover { color: rgb(255, 0, 0); background: rgb(255, 255, 255); border: 3px solid black; transition: all ease-in-out 0.2s; overflow: hidden; cursor: pointer; } </style> </head> <body> <h1>You didn't click any button.</h1> <button>Button 1</button> <button>Button 2</button> <button>Button 3</button> <button>Button 4</button> <script> var heading = document.querySelector("h1"); const btn = document.querySelectorAll("button"); // 使用forEach遍历所有按钮 btn.forEach(button => { button.addEventListener("click", function() { var txt = this.innerHTML; heading.innerHTML = txt + " is clicked."; }); }); </script> </body> </html>
额外优化提示
- 避免在循环内部定义函数
func,将其移到循环外或改用箭头函数,代码更规范 - 若按钮内无HTML内容,推荐用
textContent代替innerHTML获取文本,安全性更高
内容的提问来源于stack exchange,提问作者devYousuf
相关产品推荐
相关产品推荐

