HTMLCollection、NodeLists 和对象数组的区别

IT技术 javascript jquery dom
2021-02-10 01:11:09

当涉及到 DOM 时,我一直在 HTMLCollections、对象和数组之间感到困惑。例如...

  1. document.getElementsByTagName("td")和 和有什么不一样$("td")
  2. $("#myTable")$("td")是对象(jQuery 对象)。为什么 console.log 还显示旁边的 DOM 元素数组,并且它们不是对象也不是数组?
  3. 什么是难以捉摸的“NodeLists”,我该如何选择一个?

还请提供对以下脚本的任何解释。

[123,"abc",321,"cba"]=[123,"abc",321,"cba"]
{123:123,abc:"abc",321:321,cba:"cba"}=Object { 123=123, abc="abc", 321=321, more...}
Node= Node { ELEMENT_NODE=1, ATTRIBUTE_NODE=2, TEXT_NODE=3, more...}
document.links= HTMLCollection[a #, a #]
document.getElementById("myTable")= <table id="myTable">
document.getElementsByClassName("myRow")= HTMLCollection[tr.myRow, tr.myRow]
document.getElementsByTagName("td")= HTMLCollection[td, td, td, td]
$("#myTable")= Object[table#myTable]
$("td")= Object[td, td, td, td]


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
        <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> 
        <title>Collections?</title>  
        <script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script> 
        <script type="text/javascript">
            $(function(){
                console.log('[123,"abc",321,"cba"]=',[123,"abc",321,"cba"]);
                console.log('{123:123,abc:"abc",321:321,cba:"cba"}=',{123:123,abc:"abc",321:321,cba:"cba"});
                console.log('Node=',Node);
                console.log('document.links=',document.links);
                console.log('document.getElementById("myTable")=',document.getElementById("myTable"));
                console.log('document.getElementsByClassName("myRow")=',document.getElementsByClassName("myRow"))
                console.log('document.getElementsByTagName("td")=',document.getElementsByTagName("td"));
                console.log('$("#myTable")=',$("#myTable"));
                console.log('$("td")=',$("td"));
            });
        </script>
    </head>

    <body>
        <a href="#">Link1</a>
        <a href="#">Link2</a>
        <table id="myTable">
            <tr class="myRow"><td>td11</td><td>td12</td></tr>
            <tr class="myRow"><td>td21</td><td>td22</td></tr>
        </table>
    </body> 
</html>
6个回答

首先,我将解释之间的差异NodeListHTMLCollection

两个接口是集合DOM节点。它们在提供的方法和可以包含的节点类型方面有所不同。虽然 aNodeList可以包含任何节点类型,但 anHTMLCollection应该只包含 Element 节点。
AnHTMLCollection提供与 a 相同的方法NodeList,另外还有一个称为 的方法namedItem

当必须为多个节点提供访问权限时,总是使用集合,例如,大多数选择器方法(例如getElementsByTagName)返回多个节点或获取对所有子节点的引用(element.childNodes)。

有关更多信息,请查看DOM4 规范 - 集合

document.getElementsByTagName("td")和 和有什么不一样$("td")

getElementsByTagName是DOM接口的方法。它接受一个标签名称作为输入并返回一个HTMLCollection(参见DOM4 规范)。

$("td")大概是jQuery。它接受任何有效的 CSS/jQuery 选择器并返回一个 jQuery 对象。

标准 DOM 集合和 jQuery 选择之间的最大区别在于 DOM 集合通常是实时的(尽管并非所有方法都返回实时集合),即,对 DOM 的任何更改都会反映在集合中,如果它们受到影响。它们就像DOM 树上视图,而 jQuery 选择是调用函数时 DOM 树的快照。

为什么 console.log 还显示旁边的 DOM 元素数组,并且它们不是对象也不是数组?

jQuery 对象是类似数组的对象,即它们具有数字属性和一个length属性(请记住,数组本身就是对象)。浏览器倾向于以特殊方式显示数组和类似数组的对象,例如[ ... , ... , ... ].

什么是难以捉摸的“NodeLists”,我该如何选择一个?

请参阅我的答案的第一部分。您不能选择 NodeLists,它们是选择结果

据我所知,甚至没有一种以NodeList编程方式创建s的方法(即创建一个空的并稍后添加节点),它们仅由某些 DOM 方法/属性返回。

我希望它们都是数组
2021-03-13 01:11:09
@FelixKling:您应该提到并非所有NodeLists都是实时的。
2021-03-14 01:11:09
@KrzysztofGrzybek 没错,而且非常烦人。为什么他们中的一个有.forEach()而另一个没有?
2021-03-30 01:11:09
似乎我在 NodeList 中存在的方法“keys”、“entries”和“forEach”,但在 HTMLCollection 中缺失
2021-04-03 01:11:09
@user1032531:好吧,如果您对选定的 DOM 元素之一进行任何更改(例如添加一个子元素),那么您当然会看到更改,因为它是同一个 DOM 元素。但是,假设您选择了所有td元素,td稍后添加新元素将不会自动更新选择以包含新元素。
2021-04-09 01:11:09

0. anHTMLCollection和 a 和有NodeList什么不一样?

这里有一些定义供您参考。

DOM 级别 1 规范 - 杂项对象定义

接口 HTMLCollection

HTMLCollection 是一个节点列表。可以通过序数索引或节点的名称或 id 属性访问单个节点。注意:HTML DOM 中的集合被假定为活动的,这意味着它们会在底层文档更改时自动更新。

DOM 级别 3 规范 - NodeList

接口节点列表

NodeList 接口提供了节点有序集合的抽象,而不定义或限制该集合的实现方式。DOM 中的 NodeList 对象是活动的。

NodeList 中的项目可以通过一个整数索引访问,从 0 开始。

所以它们都可以包含实时数据,这意味着 DOM 会在它们的值更新时更新。它们还包含一组不同的功能。

您会注意到,如果您在运行脚本时检查控制台,tableDOM 元素同时包含 achildNodes NodeList[2]和 a children HTMLCollection[1]他们为什么不同?因为HTMLCollection只能包含元素节点,所以 NodeList 还包含一个文本节点。

在此处输入图片说明

1.之间有什么区别document.getElementsByTagName("td")$("td")

document.getElementsByTagName("td")返回DOM元件的阵列(一NodeList),$("td")被称为jQuery对象从具有所述元件document.getElementsByTagName("td")上其属性012等,主要的区别是,jQuery对象较慢检索一点点,但可以访问所有的方便jQuery 函数。

2.$("#myTable")$("td")是对象(jQueryobjects)。为什么console.log还在它们旁边显示 DOM 元素的数组,它们不是对象而不是数组?

他们对自己的属性的对象012等一系列的DOM元素。这是一个简单的例子:它是如何工作的:

js小提琴

    var a = {
        1: "first",
        2: "second"
    }
    alert(a[1]);

3. 什么是难以捉摸的“NodeLists”,我该如何选择?

您一直在代码中检索它们,getElementsByClassName并且getElementsByTagName都返回NodeLists

节点列表

您是如何在第三个响应中显示 DOM 的?谢谢!
2021-03-19 01:11:09
第 3 点是完全错误的。getElementsByClassName 和 getElementsByTagName 返回 HTMLCollections 而不是 NodeLists。querySelector 和 querySelectorAll 将返回一个 NodeList。
2021-03-19 01:11:09
类似数组的日志主要是length属性的结果,而不是数字属性名称的结果。你的警告字符串的例子与什么有关console.log
2021-03-24 01:11:09
这展示了如何在对象上拥有数字属性。我试图强调它们是对象而不是数组的事实。
2021-04-01 01:11:09
@user1032531 那是 Chrome 开发工具。顺便说一下,我更新了答案的开头。
2021-04-02 01:11:09

附加说明

HTMLCollection 和 NodeList 有什么区别?

的HTMLCollection只包含元素节点(标签)和节点列表包含了所有的节点

最重要的节点类型:

  1. 元素节点
  2. 属性节点
  3. 文本节点
  4. 评论节点

节点类型

元素内的空白被视为文本,文本被视为节点。

考虑以下:

<ul id="myList">
  <!-- List items -->
  <li>List item 1</li> 
  <li>List item 2</li>
  <li>List item 3</li>
  <li>List item 4</li>
  <li>List item 5</li>
</ul>

空格: <ul id="myList"> <li>List item</li></ul>

没有空格: <ul id="myList"><li>List item</li></ul>

HTMLCollection 和 NodeList 之间的区别

这么多已被告知了,但想到答案更概括版本为例来解释之间的差异HTMLCollection,并NodeList会有所帮助。

DOM 中的节点类型

  • 有 12 种不同的节点类型,它们可能有各种节点类型的子节点:

在此处输入图片说明

  • 我们可以使用以下三个属性来检查和查询 DOM 中的节点:

    • nodeType 财产
    • nodeName 财产
    • nodeValue 财产
  • nodeType属性以数字形式返回指定节点的节点类型。

    • 如果节点是元素节点,则该nodeType属性将返回1
    • 如果节点是属性节点,则该nodeType属性将返回2
    • 如果节点是文本节点,则该nodeType属性将返回3
    • 如果节点是评论节点,则该nodeType属性将返回8
    • 此属性是只读的。

HTMLCollection 与 NodeList

在此处输入图片说明

我们可以理解之间的区别HTMLCollectionNodeList更清晰地用下面的例子。请尝试在您自己的浏览器控制台中检查输出以更好地理解。

<ul>
  <li>foo</li>
  <li>bar</li>
  <li>bar</li>
</ul>
// retrieve element using querySelectorAll
const listItems_querySelector = document.querySelectorAll('li');
console.log('querySelector', listItems_querySelector);

// retrieve element using childNodes
const list  = document.querySelector('ul')
const listItems_childNodes = list.childNodes;
console.log('childNodes', listItems_childNodes);
const listItems_children = list.children;
console.log('children', listItems_children);

const listItems_getElementsByTagName = document.getElementsByTagName('li');
console.log('getElementsByTagName', listItems_getElementsByTagName);

console.log('*************************');
console.log('add one list item');
console.log('*************************');
list.appendChild(document.createElement('li'));

console.log('querySelector', listItems_querySelector);
console.log('childNodes', listItems_childNodes);
console.log('children', listItems_children);
console.log('getElementsByTagName', listItems_getElementsByTagName);

console.log('*************************');
console.log('add one more list item');
console.log('*************************');
listItems_getElementsByTagName[0].parentNode.appendChild(document.createElement('li'));

console.log('querySelector', listItems_querySelector);
console.log('childNodes', listItems_childNodes);
console.log('children', listItems_children);
console.log('getElementsByTagName', listItems_getElementsByTagName); 

$("td")是扩展的 jQuery 对象,它具有 jQuery 方法,它返回包含 html 对象数组的 jquery 对象。document.getElementsByTagName("td")是原始 js 方法并返回 NodeList。看这篇文章

谢谢卡拉克苏娜。是的,我看过那篇文章。不知道它是否有帮助,但肯定让我问了更多问题:)
2021-03-31 01:11:09
谢谢@karaxuna。有用的文章,解释得很好。
2021-04-08 01:11:09