草庐IT

HTMLCollection 和 Nodelist 的异同?

不准显示 2023-03-28 原文

HTMLCollection 和 Nodelist 的异同?

1. w3 关于这两者的定义

HTMLCollection: An HTMLCollection is a list of nodes. An individual node may be accessed by either ordinal index or the node's name or id attributes. Note: Collections in the HTML DOM are assumed to be live meaning that they are automatically updated when the underlying document is changed.

NodeList: The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.

The items in the NodeList are accessible via an integral index, starting from 0.

HTMLCollectionNodeList 都是元素节点的集合, 前者可以按照索引/节点name/节点id 属性访问。 后者可以按照索引访问。

1.1 实例属性

HTMLCollectionNodeList 都只有一个实例属性:

  • length: 返回节点集合的长度

1.2 实例方法

HTMLCollection NodeList
HTMLCollection.item()
传入元素 index 返回特定的节点
NodeList.item()
传入索引返回特定节点
HTMLCollection.namedItem()
传入节点的 name 属性,返回特定的节点
NodeList.entries()
返回key-value 的迭代器
⚠️HTMLCollection 没有 forEach 方法 NodeList.forEach()
节点遍历方法
NodeList.keys()
返回NodeList 的所有key值的迭代器,这里也就是索引
NodeList.values()
返回NodeList 的所有value值的迭代器,也就四节点本身

一些示例:

  <body>
    <p name="p1" class="para">Lorem, ipsum dolor.</p>
    <p name="p2" class="para">Lorem ipsum dolor sit amet.</p>
    <p name="p3" class="para">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
  </body>
  <script>
    const paras = document.getElementsByClassName('para');
    console.log(paras.item(0).innerHTML);//Lorem, ipsum dolor.
    console.log(paras.namedItem('p3').innerHTML);//Lorem ipsum dolor sit amet, consectetur adipisicing elit.
  </script>
  <body>
    <p name="p1" class="para">Lorem, ipsum dolor.</p>
    <p name="p2" class="para">Lorem ipsum dolor sit amet.</p>
    <p name="p3" class="para">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
  </body>
  <script>
    const paras = document.querySelectorAll('.para');
    console.log('log1:', paras.item(0).innerHTML);
    console.log('log2:', paras.entries());
    console.log('log3:', paras.entries().next());
    console.log('log4:', paras.keys());
    console.log('log5:', paras.keys().next());
    console.log('log6:', paras.values());
    console.log('log7:', paras.values().next());
    paras.forEach((p) => {
      console.log('[p.innerHTML]: ', p.innerHTML);
    });
  </script>

特别说明,在实例方法中, NodeList/HTMLCollection.item()方法仅接受索引值。

2. 哪些常见操作会返回这二者?

HTMLCollection

  • document.getElementsByTagName

  • document.getElementsByClassName

  • HTMLElement.children

  • document.forms

  • document.images

NodeList:

  • document.getElementsByName
  • document.querySelectorAll
  • HTMLElement.childNodes

3. 二者有什么相同点?

二者所包含的结点都是响应式的,也就是说,当所依赖的文档发生了变化,相应的DOM视图也会发生更新。

NodeList

为了验证这一点,我们可以使用 Array.from(浅拷贝来测试一下):

  <script>
    const paras = document.querySelectorAll('.para');
    const copy = Array.from(paras);
    copy.forEach((cp) => {
      cp.innerHTML += new Date().toLocaleTimeString();
    });
    paras.forEach((p) => {
      console.log('[p.innerHTML]: ', p.innerHTML);
    });
      //[p.innerHTML]:  Lorem, ipsum dolor.9:42:54 AM
      //[p.innerHTML]:  Lorem ipsum dolor sit amet.9:42:54 AM
      //[p.innerHTML]:  Lorem ipsum dolor sit amet, consectetur adipisicing 
  </script>

说明拷贝对象中的DOM 元素发生了变化,视图会发生更新。

HTMLCollection

对于 HTMLCollection 也是这样的,

  <script>
    const paras = document.getElementsByClassName('para');
    const copy = Array.from(paras);
    copy.forEach((cp) => {
      cp.innerHTML += new Date().toLocaleTimeString();
    });
    [...paras].forEach((p) => {
      console.log('[p.innerHTML]: ', p.innerHTML);
    });
      //[p.innerHTML]:  Lorem, ipsum dolor.9:42:54 AM
      //[p.innerHTML]:  Lorem ipsum dolor sit amet.9:42:54 AM
      //[p.innerHTML]:  Lorem ipsum dolor sit amet, consectetur adipisicing elit.9:42:54 AM
  </script>

需要注意的是,这里HTMLCollection 类数组是没有forEach 方法的, 所有我们用扩展元算符(其实也是浅拷贝)将其转换成了一个数组。

4. 二者有什么区别?

最重要的区别是, HTMLCollection 仅包含 tags(以及id/name分别标记的) 元素, 而 NodeList 包含所有的节点。 例如:

  • 元素节点

  • 属性节点

  • 文本节点(空白字符也会被视作文本节点)

  • 注释节点

    node types

示例:

  <body>
    <ul id="myList">
      <!-- List items -->
      <li name="li-name-01" id="li-id-01">List item 1</li>
      <li name="li-name-02" id="li-id-02">List item 2</li>
      <li name="li-name-03" id="li-id-03">List item 3</li>
      <li name="li-name-04" id="li-id-04">List item 4</li>
      <li name="li-name-05" id="li-id-05">List item 5</li>
    </ul>
  </body>
  <script>
    const ul = document.getElementById('myList');
    console.log('[ul.children]: ', ul.children);
    console.log('[ul.childNodes]: ', ul.childNodes);
  </script>

这意味着,对于有id节点的 HTMLCollection 返回类型, 你可以这样去访问:

console.log('[li[0]]: ', li[0]); //li#li-01
console.log("[li['li-01']]: ", li['li-01']);//li#li-01

并且这二者完全一样:

console.log(li[0] === li['li-01']);//true

name 也是如此

另外,尽管如此,HTMLCollection/NodeList 的 item 方法依旧仅能通过索引访问,而不能够通过id/name 访问。

const li = document.getElementsByTagName('li');
const _li = document.querySelectorAll('li');

//以下打印: li#li-03
console.log('[li.item(2)]: ', li.item(2));
console.log('[_li.item(2)]: ', _li.item(2));

//以下打印: li#li-01
console.log('[li.item("")]: ', li.item(''));
console.log('[li.item("li-03")]: ', li.item('li-03'));
console.log('[_li.item("")]: ', _li.item(''));
console.log('[_li.item("li-03")]: ', _li.item('li-03'));

即item参数如果接收一个非数值参数,将默认返回第一个元素,如果没有元素,那么返回 null!

有关HTMLCollection 和 Nodelist 的异同?的更多相关文章

  1. javascript - classList.remove 是从 HTMLCollection 中删除元素吗? - 2

    我在使用JavaScript的新classListAPI时遇到了一些非常奇怪的行为,假设我们有以下HTML代码:LoremIpsumLoremIpsum以及以下JavaScript代码:varelements=document.getElementsByClassName("testing");alert(elements.length);elements[0].classList.remove("testing");alert(elements.length);第一个警报将为您提供值2,而第二个警报将返回1。似乎从元素中删除类也将其从elementsHTMLCollection中删除

  2. javascript - 如何迭代 HTMLCollection? - 2

    这个问题在这里已经有了答案:WhydoesjQueryoraDOMmethodsuchasgetElementByIdnotfindtheelement?(6个答案)IsChrome’sJavaScriptconsolelazyaboutevaluatingobjects?(7个答案)UsespreadoperatoronNodeListinTypescript(1个回答)关闭4年前。我的HTML中有一些类为node-item的元素,我使用以下方法在我的组件中访问它们:letnodeItems=document.getElementsByClassName('node-item');当

  3. javascript - 针对 NodeList 调用 Array.prototype.slice 的目的是什么? - 2

    这个问题在这里已经有了答案:Explanationof[].slice.callinjavascript?(9个回答)Howdoes`Array.prototype.slice.call`work?(14个答案)Whydoesn'tnodelisthaveforEach?(10个答案)关闭3年前。我在查找如何迭代NodeLists时遇到了以下代码。varnodesArray=Array.prototype.slice.call(nodeList);nodesArray.forEach(function(node){//...})针对NodeList调用Array.prototype.s

  4. javascript - Chrome getElementsByTagName 返回 HTMLCollection 与 NodeList - 2

    我发现JavaScript函数getElementsByTagName会根据浏览器返回不同的数据。Chrome发回的HTML集合比Firefox、IE或Chromium更长(真的,更好,IMO)。我将在下面概述我的发现。我的问题本质上是“为什么Chrome会改变这个,其他浏览器也会这样做(什么时候?),以及返回的length属性有多可靠?”比较Chrome(版本34.0.1847.116m)与Chromium(版本33.0.1750.152Ubuntu13.10(256984))。我确实注意到这个Chromium版本有点落后于Chrome(v33与v34),所以它可能也在UbuntuC

  5. javascript - 将 NodeList 附加到 HTML 元素 - 2

    我有以下字符串:varsonglist='MamaTriedBlueEyesCryingIntheRain';我正在通过这个自定义函数将其转换为NodeList:vartoDom=function(str){vartmp=document.createElement("div");tmp.innerHTML=str;returntmp.childNodes;};console.log(toDom(songlist))输出NodeList[,],您可以浏览开发工具。当我尝试将集合附加到节点时...document.getElementById("app-data").appendChil

  6. javascript - 如何检查一个对象是否是 IE 中 NodeList 的实例? - 2

    为什么NodeList在IE6/7中没有定义?(function(){varel=document.getElementById('testform')['foobar[]']if(elinstanceofNodeList){alert("I'maNodeList");}})();这在FF3/Safari3.1中有效,但在IE6/7中无效。任何人都知道如何检查el是否是跨所有浏览器的NodeList实例? 最佳答案 "DuckTyping"应该始终有效:...if(typeofel.length=='number'&&typeofe

  7. javascript - 如何将两个 NodeList 对象连接成一个,避免重复 - 2

    我正在编写一些函数来简化我与Javascript节点的交互,这是目前为止的源代码:Node.prototype.getClasses=function(){returnthis.className?this.className.split(""):"";};Node.prototype.hasClass=function(c){returnthis.getClasses().indexOf(c)>=0;};Node.prototype.addClass=function(c){if(!this.hasClass(c)){this.className+=""+c;}returnthis;

  8. javascript - 将 NodeList 转换为数组 - 2

    我很难将NodeList转换为IE8中的数组。以下内容在Chrome中完美运行,但在IE8中toArray()不是被认为有效:NodeList.prototype.toArray=function(){vara=[];for(vari=0,len=this.length;i我尝试向数组添加原型(prototype)函数只是为了检查我的理智并且它工作正常。这让我觉得IE8实际上并没有返回NodeList?这是一个完整的例子:http://jsfiddle.net/e4RbH/我做错了什么? 最佳答案 如果您正在寻找使用ES6的现代答案

  9. javascript - js 在 nodeList 中查找对象? - 2

    后备是无关紧要的。请不要使用图书馆。我们有一个dom对象引用,我们将调用obj。它实际上是一个event.target。我们有一个节点列表,我们将调用nodes,这是我们通过querySelectorAll和一个变量选择器获得的。nodes可能有1个或多个元素,并且每个元素都可能有子元素。我们需要确定obj是那些节点元素之一,还是这些节点元素的子元素。我们在这里寻找“native”浏览器功能,我们可以编写自己的for循环并完成此操作,我们正在寻找替代方案。类似于:nodes.contains(obj)或nodes.indexof(obj)涉及其他检索要匹配的节点列表的方法的解决方案是可

  10. javascript - 从 DOM 中移除 HTMLCollection 元素 - 2

    我有一个段落元素的集合。有些是空的,有些只包含空格,而有些则有内容:Pellentesquehabitantmorbitristiquesenectusetnetusetmalesuadafamesacturpisegestas.Vestibulumtortorquam,feugiatvitae,ultricieseget,temporsitamet,ante.Doneceuliberositametquamegestassemper.Aeneanultriciesmivitaeest.Maurisplacerateleifendleo.  我正在使用getElem

随机推荐