如何理解并正确结合使用JavaScript的forEach()与call()方法
理解
forEach()与call()的组合用法及代码改写 核心逻辑解释
你看到的array.forEach.call(elems, function(el) { ... })本质是**"借方法"**:
document.querySelectorAll(".active")返回的是NodeList(类数组对象),早期JS环境里,NodeList没有自带的forEach方法,所以开发者会借用数组的forEach来遍历它。call()的作用是修改forEach方法内部的this指向——原本array.forEach()里的this是array,用call(elems)之后,forEach就会把elems当成要遍历的集合,逐个调用回调函数。- 简单说:让数组的
forEach方法,去处理NodeList这个类数组对象。
等价代码改写(帮你理解)
写法1:用现代NodeList自带的forEach(推荐)
现在主流浏览器的NodeList已经支持forEach了,可以直接写:
let parentElement = document.getElementById("node1"); parentElement.addEventListener("click", (e) => { var elems = document.querySelectorAll(".active"); // 直接调用NodeList的forEach elems.forEach(function(el) { el.classList.remove("active"); }); e.target.classList.add("active"); // 优化:保留原有类名 });
写法2:用基础for循环(最直观)
如果不用forEach,用普通循环也能实现,逻辑更直白:
let parentElement = document.getElementById("node1"); parentElement.addEventListener("click", (e) => { var elems = document.querySelectorAll(".active"); // 遍历类数组的NodeList for(let i = 0; i < elems.length; i++) { elems[i].classList.remove("active"); } e.target.classList.add("active"); // 优化:保留原有类名 });
写法3:把NodeList转成数组再用forEach
先把类数组转成真正的数组,再用数组原生的forEach:
let parentElement = document.getElementById("node1"); parentElement.addEventListener("click", (e) => { var elems = document.querySelectorAll(".active"); // 转成数组:两种方式都可行 let elemArray = Array.from(elems); // 或者 let elemArray = [...elems]; elemArray.forEach(function(el) { el.classList.remove("active"); }); e.target.classList.add("active"); // 优化:保留原有类名 });
原代码的小提示
原代码里的e.target.className = "active"会覆盖掉元素原本的btn类,改成e.target.classList.add("active")能保留原有类名,更稳妥。
内容的提问来源于stack exchange,提问作者Jon
相关产品推荐
相关产品推荐

