HTMLCollection 与 NodeList 区别

比较 HTMLCollection 和 NodeList 的获取方式、内容类型和动态特性

问题

HTMLCollection 和 NodeList 有什么区别?

解答

获取方式

// HTMLCollection
const byId = document.getElementsByClassName('item');
const byTag = document.getElementsByTagName('div');
const children = document.body.children;

// NodeList
const byQuery = document.querySelectorAll('.item');  // 静态
const childNodes = document.body.childNodes;          // 动态

包含内容

const container = document.getElementById('container');

// HTMLCollection - 只包含元素节点
console.log(container.children);
// HTMLCollection [div, span, p]

// NodeList - 包含所有节点(元素、文本、注释等)
console.log(container.childNodes);
// NodeList [text, div, text, span, text, p, text]

动态性差异

<ul id="list">
  <li>1</li>
  <li>2</li>
</ul>

<script>
const list = document.getElementById('list');

// HTMLCollection - 始终是动态的
const htmlCollection = list.getElementsByTagName('li');

// NodeList - querySelectorAll 返回静态,childNodes 返回动态
const staticNodeList = list.querySelectorAll('li');
const liveNodeList = list.childNodes;

console.log(htmlCollection.length); // 2
console.log(staticNodeList.length); // 2

// 添加新元素
const newLi = document.createElement('li');
newLi.textContent = '3';
list.appendChild(newLi);

console.log(htmlCollection.length);  // 3 - 自动更新
console.log(staticNodeList.length);  // 2 - 保持不变
</script>

可用方法

const nodeList = document.querySelectorAll('div');
const htmlCollection = document.getElementsByTagName('div');

// NodeList 支持 forEach
nodeList.forEach(node => console.log(node));

// HTMLCollection 不支持 forEach,需要转换
// 方法1:Array.from
Array.from(htmlCollection).forEach(el => console.log(el));

// 方法2:展开运算符
[...htmlCollection].forEach(el => console.log(el));

// 方法3:借用数组方法
Array.prototype.forEach.call(htmlCollection, el => console.log(el));

访问方式

// 两者都支持索引访问和 item() 方法
nodeList[0];
nodeList.item(0);

htmlCollection[0];
htmlCollection.item(0);

// HTMLCollection 额外支持 namedItem(),通过 id 或 name 访问
// <div id="myDiv"></div>
htmlCollection.namedItem('myDiv');
htmlCollection['myDiv'];  // 简写形式

关键点

  • 内容类型:HTMLCollection 只含元素节点,NodeList 可含所有节点类型
  • 动态性:HTMLCollection 始终动态;NodeList 中 querySelectorAll 返回静态,childNodes 返回动态
  • 遍历方法:NodeList 有 forEach,HTMLCollection 需转为数组才能用
  • 获取方式getElementsBy* 返回 HTMLCollection,querySelectorAll 返回 NodeList
  • 命名访问:HTMLCollection 支持 namedItem() 按 id/name 访问元素