NodeList研究

先来看一段代码


      const hchild = document.head.childNodes
      const bchild = document.body.childNodes
      const hsize = hchild.length
      const bsize = bchild.length
      document.head.appendChild(bchild[0])
      console.log(`${hchild.length === hsize} and ${bchild.length === bsize}`)

浏览器中执行后,输出是什么呢?

答,输出是false和false

第一个false还稍微容易理解一些,hchild是指向head.childNodes的指针,调用appendChild后,长度增加了1 。

第二个false一开始让我懵逼了,为什么bchild.length也发生了变化呢?因为body.childNodes返回的并不是数组,而是一个NodeList。

Although NodeList is not an Array, it is possible to iterate on it using forEach(). Several older browsers have not implemented this method yet. You can also convert it to an Array using Array.from. In some cases, the NodeList is a live collection, which means that changes in the DOM are reflected in the collection.

译:尽管NodeList并非一个数组,但仍然可以使用forEach迭代。一些老旧的浏览器还没有实现这个方法,你可以使用Array.from将之转换成一个数组。某些情况下,NodeList时一个动态集合,这意味着DOM的变化会反应到collection中

转数组什么的,都不重要,最关键的是最后一句话:==the NodeList is a live collection, which means that changes in the DOM are reflected in the collection.==它就是为什么,两个执行结果都变成了false的原因。

如果按照数组去理解bchild,那么其length不应该变化,但childNodes是动态集合。在执行完毕appendChild之后,原来bchild[0]元素已经不再属于body.childNodes,故其长度会发生变化。

在React v0.3.0源码中,存在这类似的代码


  for (var i = 0; i < originalLength; i++) {
    ret =
      insertNodeAfterNode(parentRootDomNode, htmlCollection[0], ret || after);
  }

上述代码的htmlCollection就是一个NodeList,可以发现,这个循环一直在访问htmlCollection[0],但因为每次执行insertNodeAfterNode时,都会对htmlCollection[0]执行insert或者append方法,因此,在这个for循环里,完成了对htmlCollection的遍历。

Show Comments

Get the latest posts delivered right to your inbox.