Разница между HTMLCollection, NodeLists и массивами объектов

Я всегда был в замешательстве между HTMLCollections, объектами и массивами, когда дело доходит до DOM. Например...

  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>

5 ответов

Решение

Сначала я объясню разницу между NodeList а также HTMLCollection,

Оба интерфейса являются коллекциями узлов DOM. Они различаются по методам, которые они предоставляют, и по типу узлов, которые они могут содержать. В то время как NodeList может содержать любой тип узла, HTMLCollection должен содержать только узлы элемента.
HTMLCollection предоставляет те же методы, что и 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С программной точки зрения (т.е. создание пустого и добавление узлов позже), они возвращаются только некоторыми методами / свойствами DOM.

0. В чем разница между HTMLCollection и NodeList ?

Вот несколько определений для вас.

DOM Level 1 Spec - Разные определения объектов:

Интерфейс HTMLCollection

HTMLCollection - это список узлов. К отдельному узлу можно получить доступ либо по порядковому индексу, либо по атрибутам имени или идентификатора узла. Примечание. Предполагается, что коллекции в HTML DOM являются живыми, что означает, что они автоматически обновляются при изменении базового документа.

DOM Level 3 Spec - NodeList

Интерфейс NodeList

Интерфейс NodeList обеспечивает абстракцию упорядоченной коллекции узлов, не определяя и не ограничивая способ реализации этой коллекции. Объекты NodeList в DOM являются живыми.

Элементы в NodeList доступны через интегральный индекс, начиная с 0.

Таким образом, они могут содержать живые данные, что означает, что DOM будет обновляться, когда их значения будут. Они также содержат другой набор функций.

Если вы будете проверять консоль, если вы запустите свои скрипты, вы заметите, что table Элемент DOM содержит как childNodesNodeList[2] и childrenHTMLCollection[1], Почему они разные? Так как HTMLCollection может содержать только узлы элементов, NodeList также содержит текстовые узлы.

1. В чем разница между document.getElementsByTagName("td") а также $("td")?

document.getElementsByTagName("td") возвращает массив элементов DOM (NodeList), $("td") называется объектом JQuery, который имеет элементы из document.getElementsByTagName("td") по своим свойствам 0, 1, 2и т. д. Основное отличие состоит в том, что объект jQuery немного медленнее извлекается, но дает доступ ко всем удобным функциям jQuery.

2. $("#myTable") а также $("td") являются объектами (jQuery объекты). Почему console.log также показывает массив элементов DOM рядом с ними, и не являются ли они объектами и не массивом?

Это объекты со своими свойствами 0, 1, 2 и т. д. для элементов DOM. Вот простой пример: как это работает:

jsFiddle

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

3. Что такое неуловимые списки NodeLists и как их выбрать?

Вы извлекаете их в свой код, getElementsByClassName а также getElementsByTagName оба возвращаются NodeList s

NodeList

Дополнительное примечание

В чем разница между HTMLCollection и NodeList?

HTMLCollection содержит только узлы элементов (теги), а NodeList содержит все узлы.

Существует четыре типа узлов:

  1. элемент узла
  2. атрибутивный узел
  3. текстовый узел
  4. узел комментария

nodeTypes

Пробелы внутри элементов рассматриваются как текст, а текст - как узлы.

Учтите следующее:

<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

Мы можем понять разницу между HTMLCollection а также NodeListболее наглядно на следующем примере. Пожалуйста, попробуйте проверить выходные данные в консоли вашего собственного браузера, чтобы лучше понять.

<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, он возвращает объект jquery, который содержит массив объектов html. document.getElementsByTagName("td") является сырым методом js и возвращает NodeList. Смотрите эту статью

Объекты NodeList являются коллекциями узлов, возвращаемых, например, x. Свойство childNodes или метод document.querySelectorAll(). В некоторых случаях NodeList является активным, что означает, что изменения в DOM автоматически обновляют коллекцию! Например, Node.childNodes является живым:

var c = parent.childNodes; //assume c.length is 2
parent.appendChild(document.createElement('div'));
//now c.length is 3, despite the `c` variable is assigned before appendChild()!!
//so, do not cache the list's length in a loop.

Но в некоторых других случаях NodeList являетсястатическим, где любые изменения в DOM не влияют на содержимое коллекции. querySelectorAll () возвращает статический NodeList.

HTMLCollection- этоживая и упорядоченная коллекция элементов (она автоматически обновляется при изменении базового документа). Это может быть результатом таких свойств как дочерние или методы, как document.getElementsByTagName (), и может иметь только HTMLElement в качестве своих элементов.

HTMLCollection также предоставляет свои члены напрямую как свойства по имени и индексу:

var f = document.forms; // this is an HTMLCollection
f[0] === f.item(0) === f.myForm //assume first form id is 'myForm'

HTMLElement - это просто один тип узлов:

Узел << HTMLElement наследование

Узел может быть нескольких типов. Наиболее важными из них являются следующие:

  • element (1): узел элемента, такой как<p>или же<div>,
  • Атрибут (2): Атрибут элемента. Атрибуты элемента больше не реализуют интерфейс Node в спецификации DOM4!
  • текст (3): фактический текст элемента или атрибута.
  • комментарий (8): узел комментария.
  • документ (9): узел документа.

Таким образом, большая разница в том, что HTMLCollection содержит только HTMLElements, но NodeList также содержит комментарии, пробельные тексты (символы возврата каретки, пробелы..) и т. Д. Проверьте это, как в следующем фрагменте:

function printList(x, title) {
  console.log("\r\nprinting "+title+" (length="+x.length+"):");
  for(var i=0; i<x.length; i++) {
    console.log("  "+i+":"+x[i]);
  }
}

var elems = document.body.children; //HTMLCollection
var nodes = document.body.childNodes; //NodeList

printList(elems, "children [HTMLCollection]");
printList(nodes, "childNodes [NodeList]");
<div>para 1</div><!-- MyComment -->
<div>para 2</div>

И HTMLCollection, и NodeList содержат свойство length, которое можно использовать для циклического перемещения по их элементам. Не используйте for... in или для каждого... in для перечисления элементов в NodeLists, так как они также перечисляют его длину и свойства элемента и вызывают ошибки, если ваш сценарий предполагает, что он имеет дело только с объектами элемента. Кроме того, for..in не гарантируется посещение свойств в любом конкретном порядке.

for (var i = 0; i < myNodeList.length; i++) {
  var item = myNodeList[i];
}
Другие вопросы по тегам