queryselectorall 返回 nodelist 而非数组,需用[...nodes]或array.from()转数组才能调用foreach;style属性名须驼峰式(如backgroundcolor);批量改样式优先用classlist;foreach中避免this误用和闭包陷阱。

querySelectorAll 返回的是 NodeList,不是数组
很多人直接写 document.querySelectorAll('.btn').forEach(...) 报错,提示 forEach is not a function。这是因为老版本浏览器(如 IE)返回的 NodeList 不原生支持 forEach,即使现代浏览器支持,它也**不是 Array 实例**,Array.prototype.forEach 不能直接调用。
实操建议:
- 用扩展运算符转成数组:
[...document.querySelectorAll('.btn')].forEach(...) - 用
Array.from():Array.from(document.querySelectorAll('.btn')).forEach(...) - 更轻量的写法(不兼容 IE):
document.querySelectorAll('.btn').forEach?.(...)(可选链 + 现代环境)
修改 style 属性时注意 camelCase 写法
DOM 元素的 style 对象只认 JavaScript 风格的属性名,比如 backgroundColor,而不是 CSS 里的 background-color。写错就静默失败,没报错但样式不生效。
常见映射示例:
-
font-size→fontSize -
z-index→zIndex -
border-radius→borderRadius -
line-height→lineHeight
错误写法:el.style['background-color'] = 'red'(无效)
正确写法:el.style.backgroundColor = 'red'
批量改样式优先用 classList 而非 style
直接操作 el.style.xxx 是内联样式,优先级高、难维护、无法复用 CSS 变量或媒体查询。多数场景下,应该用 classList 切换预定义类名。
实操建议:
- 加类:
el.classList.add('active') - 删类:
el.classList.remove('disabled') - 切换(有则删,无则加):
el.classList.toggle('highlight') - 一次操作多个类:
el.classList.add('a', 'b', 'c')
如果必须动态设值(比如颜色来自 JS 变量),再用 style;否则一律走 CSS 类控制。
forEach 里 this 指向和闭包变量容易出错
在 forEach 回调里用 this,默认是 undefined(严格模式)或全局对象,不是你期望的元素。另外,循环中异步操作(如 setTimeout)容易捕获到同一个 el 引用,导致最后都作用在最后一个元素上。
典型陷阱代码:
document.querySelectorAll('.item').forEach(function() {
setTimeout(() => console.log(this)); // this 是 undefined
});
安全写法:
- 显式传参:
forEach((el) => { el.style.color = 'blue'; }) - 避免在 forEach 里写异步逻辑;真要延时,用
el.dataset.index或闭包绑定当前元素 - 需要 this 指向元素?用箭头函数或
bind(el),但更推荐直接用参数el
真正麻烦的不是语法,而是样式变更后是否触发重排(reflow)、是否被后续 CSS 规则覆盖、是否影响无障碍语义——这些得靠 DevTools 的 Computed 标签和 Accessibility 面板去验证,光写对 JS 远不够。










