为何替换for循环为for...in后,Tab组件的JS函数会中断?
为什么用
for...in遍历Tab内容后函数会中断? 这是个很典型的for...in误用场景,我来给你拆解下问题根源:
1. 先搞清楚getElementsByClassName返回的是什么
document.getElementsByClassName("tabcontent")返回的是HTMLCollection——这是一个类数组对象,它看起来像数组,但本质上是浏览器提供的特殊对象,除了包含对应索引的DOM元素,还自带了length、item()、namedItem()这些可枚举属性。
2. for...in的行为不是你想的那样
for...in循环的作用是遍历对象的所有可枚举属性,包括原型链上继承来的属性。当你用它遍历HTMLCollection时,它不仅会遍历0、1、2这些对应DOM元素的索引,还会把length、item这些属性也遍历进去。
3. 报错导致函数中断
当循环到length这类非DOM元素的属性时,tabcontent[i]就不是一个DOM节点了,尝试访问它的.style.display会直接抛出TypeError(因为普通对象没有style属性)。浏览器遇到未捕获的错误时会终止当前函数的执行,所以你看到后续的所有代码都被跳过了。
解决办法
推荐几种替代方案,选你习惯的就行:
方案1:继续使用传统for循环(最稳妥的经典写法)
tabcontent = document.getElementsByClassName("tabcontent"); for (i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; }
方案2:转成真正的数组后用for...of(现代写法)
把HTMLCollection转换成数组,就能用更简洁的for...of循环,它只会遍历数组的元素:
const tabcontent = Array.from(document.getElementsByClassName("tabcontent")); for (const content of tabcontent) { content.style.display = "none"; }
方案3:转成数组后用forEach
同样先转数组,然后用数组的forEach方法:
Array.from(document.getElementsByClassName("tabcontent")).forEach(content => { content.style.display = "none"; });
总结一下:for...in是为遍历普通对象的键设计的,绝对不要用它遍历类数组对象(比如HTMLCollection、NodeList),否则很容易因为遍历到非预期属性而触发错误。
内容的提问来源于stack exchange,提问作者La Mort
相关产品推荐
相关产品推荐

