getElementsByClassName 返回 HTMLCollection,需转数组才能用 forEach 等方法;querySelectorAll 返回可直接遍历的静态 NodeList,语法更灵活、推荐优先使用。

getElementsByClassName 返回的是 HTMLCollection,不是数组
它看起来像数组(有 length、能用索引访问),但没有 map、forEach、filter 这些方法。直接写 document.getElementsByClassName('btn').forEach(...) 会报 TypeError: is not a function。
常见应对方式:
- 用
Array.from()转成真数组:Array.from(document.getElementsByClassName('btn')).forEach(...) - 用扩展运算符:
[...document.getElementsByClassName('btn')].forEach(...) - 用传统
for循环(性能略好,尤其集合很大时):for (let i = 0; i
类名含空格会被当作多个独立类处理
getElementsByClassName('header active') 不是找同时含 header 和 active 两个类的元素,而是找类名为 "header active"(即整个字符串是一个类名)的元素——这在实际 HTML 中极少见,通常是你想用 querySelectorAll('.header.active')。
正确理解:
立即学习“前端免费学习笔记(深入)”;
-
getElementsByClassName('a b')→ 查找 class 属性值**恰好等于**"a b"的元素(中间不能多空格,也不能少) - 要找同时有
a和b类的元素,请用document.querySelectorAll('.a.b') - 类名区分大小写,
getElementsByClassName('Nav')不会匹配class="nav"
动态更新的 HTMLCollection 会实时响应 DOM 变化
它不是快照,而是一个“活”的集合。比如:
const els = document.getElementsByClassName('item');
console.log(els.length); // 假设是 3
document.body.innerHTML += '<div class="item"></div>';
console.log(els.length); // 立刻变成 4
这在循环中删除自身时容易出错:
- 错误写法:
for (let i = 0; i → 实际只删掉前半部分,因为每次 <code>remove()后els实时缩短,后续索引偏移 - 安全做法:倒序遍历
for (let i = els.length - 1; i >= 0; i--),或先转成数组再操作
兼容性没问题,但现代代码更倾向 querySelectorAll
getElementsByClassName 在 IE6+ 都支持,但它能力有限:不支持复合选择、无法按嵌套关系筛选、返回类型不易操作。而 querySelectorAll('.my-class') 返回的是静态 NodeList(可直接 forEach),语法更灵活,语义更清晰。
除非你明确需要“活集合”特性,或者维护非常老的代码,否则优先用 querySelectorAll 更省心。一个容易被忽略的细节:两者对空格类名的处理逻辑完全不同,混用时极易误判结果。



















