DOM动态集合

DOM是JavaScript中重要部分之一,在DOM中有一个动态集合。

这个动态集合包含节点的集合(NodeList)、元素属性的集合(NamedNodeMap)和HTML元素的集合(HTMLCollection)。这三个对象都是类数组(Array-like),具有像数组一样的特性

类数组:比如arguments

  • 具有:指向对象元素的数字索引下标以及length属性告诉我们对象的元素个数
  • 不具有:不具有诸如push()、forEach()以及indexOf()等数组对象具有的方法

将类数组对象转换为数组

//es5
let  arr = Array.prototype.slice.call(arguments);
//es6
let  arr = Array.from(arguments);
//还可以使用ES6中的扩展运算符...将某些数据结构转换成数组,这种数据结构必须有遍历器接口。
let  arr = [...arguments];

NodeList集合

  • NodeList实例是一个类似数组的对象,它的成员是节点对象。通过以下方法可以得到NodeList实例。
    Node.childNodes
    document.querySelectorAll()、

HTMLCollection

  • 一个节点对象的集合,只能包含元素节点(element),不能包含其他类型的节点。
  • HTMLCollection的集合可以通过getElementsByTagName()、getElementsByName()、document.getElementsByClassName()、document.anchors、document.forms、document.images和documnet.links等方式来获取。

NameNodeMap集合

DOM中的Element节点是唯一拥有attributes属性的一种节点类型。而attributes属性中就包含NamedNodeMap集合。NamedNodeMap集合的元素拥有nodeName和nodeValue属性,分别表示元素节点名称和值。

三者的异同

共同点

  • 三者都具有length属性

  • 三者都有item()方法

  • 三者都是动态的,如果对NodeList和HTMLCollection中的元素进行操作都会直接反映到DOM中,因此如果一次性直接在集合中进行DOM操作,开销非常大

不同之处:

  • NodeList里面包含了所有的节点类型

  • HTMLCollection里面只包含元素节点

  • NamedNodeMap里面包含了Attribute的集合,例如id、title、class等,集合中的每一个元素都是attr类型

  • 三者所提供的方法也有不同,例如HTMLCollection中提供了namedItem(),而NodeList和NamedNodeMap两个集合中没有namedItem()方法

动态NodeList和静态NodeList

  • getElementsByTagName()方法返回一个动态(live)的HTMLCollection,
  • 而querySelectorAll()返回的是一个静态(static)的NodeList

动态集合

DOM中的NodeList和NamedNodeMap对象是动态的;也就是说,对底层文档结构的修改会动态地反映到相关的集合NodeList和NamedNodeMap中。例如,如果先获取了某个元素(Element)的子元素的动态集合NodeList对象,然后又在其他地方顺序添加更多子元素到这个DOM父元素中(可以说添加、修改、删除子元素等操作),这些更改将自动反射到NodeList,不需要手动进行其他调用。同样地,对DOM树上某个Node节点的修改,也会实时影响引用了该节点的NodeList和NamedNodeMap对象。

静态集合

querySelectorAll()方法返回的NodeList对象必须是静态的,而不能是动态的。后续对底层document的更改不能影响到返回的这个NodeList对象。这意味着返回的对象将包含在创建列表那一刻匹配的所有元素节点


    
        DOM Tree
    
    
        
Title
Item1
Item2
Item3
Item4
Item5
let box = document.getElementById('box')

let liveNodeList1 = document.getElementsByTagName('div')

console.log(liveNodeList1)
let liveNodeList2 = document.getElementsByClassName('.item')
console.log(liveNodeList2)

let liveNodeList3 = document.querySelectorAll('.item')
console.log(liveNodeList3)

let children = box.childNodes;

console.log(children, children.length)
DOM动态集合_第1张图片
1..png

为什么动态集合比静态集合更快

为什么说getElementsByTagName()在所有浏览器上都比auerySelectorAll()要快好多倍。

  • 让 querySelectorAll() 和 getElementsByTagName() 具有相同的参数和行为, 但有很大的不同点。 在前一种情况下, 返回的 NodeList 就是方法被调用时刻的文档状态的快照, 而后者总是会随时根据document的状态而更新
  • 使用getElementsByTagName()方法我们得到的结果就像是一个对象的索引,而通过querySelectorAll()方法我们得到的是一个对象的克隆;所以当这个对象数据量非常大的时候,显然克隆这个对象所需要花费的时间是很长的
let box = document.getElementById('box')
let liveNodeList = document.getElementsByTagName('div')

console.log(liveNodeList, liveNodeList.length)

let newEle = document.createElement('div')
newEle.textContent = '新创建的div元素'

box.appendChild(newEle)

console.log(liveNodeList, liveNodeList.length)
DOM动态集合_第2张图片
2.png
let box = document.getElementById('box')

let liveNodeList = document.querySelectorAll('div')

console.log(liveNodeList, liveNodeList.length)

let newEle = document.createElement('div')
newEle.textContent = '新创建的div元素'
box.appendChild(newEle)

console.log(liveNodeList, liveNodeList.length)

liveNodeList = document.querySelectorAll('div')
console.log(liveNodeList, liveNodeList.length)
DOM动态集合_第3张图片
3.png

你可能感兴趣的:(DOM动态集合)