JS之DOM篇-NodeList、HTMLCollection和NamedNodeMap动态集合

动态集合是指DOM结构的变化能够自动反映到所保存的对象中,相应的静态集合是指DOM结构的变化不会自动反映到所保存的对象中

NodeList

NodeList实例对象是一个类数组对象,它的成员是节点对象。childNodes和querySelectorAll()方法的返回值都是NodeList实例对象,但是childNodes返回的是动态集合,而querySelectorAll()方法返回的是静态结合

<div id="test"></div>
<script>
  var childNodes = test.childNodes
  console.log(childNodes, childNodes instanceof NodeList) // [] true
  
  test.appendChild(document.createElement('span')) 
  console.log(childNodes) // [span]
</script>
<div id="test"></div>
<script>
  var allDiv = test.querySelectorAll('div')
  console.log(allDiv) // []
  
  test.appendChild(document.createElement('div')) 
  console.log(allDiv) // []

  console.log(test.querySelectorAll('div')) // [div]
</script>

HTMLCollection

HTMLCollection实例对象也是一个类数组对象,它的成员也是节点对象。与NodeList集合不同的是NodeList主要是Node节点的集合,而HTMLCollection主要是元素节点(Element)的集合,元素节点只是12种Node节点中的一种。另外所有的HTMLCollection对象都是动态的,而NodeList并不一定是动态的

关于12种Node节点类型的介绍移步于此

getElementsByTagName()、getElementsByClassName()、getElementsByName()等方法的返回值,以及children、document.links、document.forms等元素集合都是HTMLCollection集合

<div id="test"></div>
<script>
  let all = test.children
  console.log(all) // []
  test.appendChild(document.createElement('div'))
  console.log(all) // [div]
</script>

NamedNodeMap

元素节点的attributes属性是NamedNodeMap实例对象,它也是一个动态集合

<div id="test"></div>
<script>
  let all = test.attributes
  console.log(all) // {0: id, id: id, length: 1}
  test.setAttribute('class', 'test')
  console.log(all) // {0: id, 1: class, id: id, class: class, length: 2}
  console.log(all instanceof NamedNodeMap) // true
</script>

注意事项

动态集合在循环时一定要小心,可能会由于忽略它的动态性而造成死循环

var divs = document.getElementsByTagName('div')
for(var i = 0; i < divs.length; i++){
  document.body.appendChild(document.createElement('div'))
}

示例中的divs是一个HTMLCollection集合,divs.length会随着循环而递增,因而会陷入死循环。为了避免这种情况发生,可以把初始的length先保存起来

var divs = document.getElementsByTagName('div'), len = divs.length
for(var i = 0; i < len; i++){
  document.body.appendChild(document.createElement('div'))
}

开发中尽量减少访问NodeList、HTMLCollection、NamedNodeMap的次数。由于其动态性,每次访问它们都会运行一次基于文档的查询。所以可以考虑将它们的值缓存起来

扩展: 函数内部有一个arguments对象,它也是一个具有动态性的类数组对象

posted @ 2021-09-29 13:04  wmui  阅读(236)  评论(0编辑  收藏  举报