JavaScript:[].forEach.call()与直接添加数组项到父节点的区别及代码解析
[].forEach.call()在DOM元素集合中的使用疑问解答 嘿,我来帮你拆解这段代码和背后的逻辑~
一、这段[].forEach.call()代码的作用是什么?
首先得明确:你的shuffledCards应该是一个DOM元素集合(比如通过document.querySelectorAll()获取的NodeList,或者getElementsByClassName()返回的HTMLCollection),它并不是标准的JavaScript数组,所以本身没有自带forEach遍历方法。
那这段代码的核心逻辑就是给DOM集合“借用”数组的遍历方法:
- 空数组
[]继承了JavaScript数组原型上的forEach方法 - 通过
call()方法,把forEach的执行上下文(也就是this指向)改成shuffledCards这个DOM集合 - 这样就能遍历集合里的每一张卡片元素
item,把它们逐个添加到deck这个父节点中
另外提个小细节:你这段代码里外层已经写了for循环,里面又嵌套了forEach,其实是冗余的——只需要保留其中一种遍历方式就行,比如直接用forEach遍历shuffledCards就足够完成卡片挂载的操作啦。
二、使用[].forEach.call()和直接添加数组项到父节点的区别?
要分两种场景来看:
1. 针对DOM集合的情况
如果shuffledCards是DOM集合(不是真数组),你没法直接用shuffledCards.forEach()(旧版浏览器里DOM集合没有原生forEach),这时候[].forEach.call()就是一种“曲线救国”的兼容写法,让你能用上数组的便捷遍历方法。而直接添加的话,你可能需要写传统的for循环:
for (let i = 0; i < shuffledCards.length; i++) { deck.appendChild(shuffledCards[i]); }
两种写法的最终效果完全一致,但forEach的写法更简洁、可读性更强。
2. 针对真数组的情况
如果shuffledCards是标准的JS数组,那你完全可以直接写shuffledCards.forEach(item => deck.appendChild(item)),不需要用[].forEach.call()——这时候[].forEach.call()就显得多此一举了。
另外还有个通用细节:当你用appendChild()把DOM元素添加到新父节点时,元素会自动从原来的父节点中移除,所以这段代码本质是把打乱后的卡片重新挂载到deck中,实现卡片布局的刷新。
内容的提问来源于stack exchange,提问作者Jakwakwa

