Sự khác biệt giữa HTMLCollection, NodeLists và mảng đối tượng


94

Tôi luôn bị nhầm lẫn giữa HTMLCollections, đối tượng và mảng khi nói đến DOM. Ví dụ...

  1. Sự khác biệt giữa document.getElementsByTagName("td")và là $("td")gì?
  2. $("#myTable")$("td")là các đối tượng (đối tượng jQuery). Tại sao console.log cũng hiển thị mảng các phần tử DOM bên cạnh chúng và chúng không phải là đối tượng và không phải là một mảng?
  3. Tất cả các "NodeLists" khó nắm bắt là gì và làm cách nào để chọn một?

Cũng vui lòng cung cấp bất kỳ diễn giải nào của tập lệnh dưới đây.

Cảm ơn bạn

[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>

Tôi nghĩ rằng tôi có thể thêm những điều sau đây cho hậu thế. (a) Trong JavaScript hiện đại, so sánh tốt hơn sẽ là giữa document.querySelectorAll('td')$('td'). (b) Sự khác biệt cơ bản là jQuery hoạt động với kiểu đối tượng của riêng nó, trong đó có chứa một tập hợp các phần tử HTML được đánh số ; bộ sưu tập này không phải là bộ sưu tập nào ở trên và đối tượng jQuery về cơ bản là một trình bao bọc xung quanh các phần tử DOM thực sự.
Manngo

Câu trả lời:


113

Đầu tiên tôi sẽ giải thích sự khác biệt giữa NodeListHTMLCollection.

Cả hai giao diện đều là tập hợp các nút DOM. Chúng khác nhau về phương thức mà chúng cung cấp và loại nút mà chúng có thể chứa. Trong khi a NodeListcó thể chứa bất kỳ loại nút nào, một HTMLCollectionđược cho là chỉ chứa các nút Phần tử.
An HTMLCollectioncung cấp các phương thức giống như a NodeListvà bổ sung một phương thức được gọi namedItem.

Bộ sưu tập luôn được sử dụng khi quyền truy cập phải được cung cấp cho nhiều nút, ví dụ: hầu hết các phương thức bộ chọn (chẳng hạn như getElementsByTagName) trả về nhiều nút hoặc nhận tham chiếu đến tất cả các nút con ( element.childNodes).

Để biết thêm thông tin, hãy xem đặc tả DOM4 - Bộ sưu tập .

Sự khác biệt giữa document.getElementsByTagName("td")và là $("td")gì?

getElementsByTagNamelà phương thức của giao diện DOM. Nó chấp nhận một tên thẻ làm đầu vào và trả về một HTMLCollection(xem đặc tả DOM4 ).

$("td")có lẽ là jQuery. Nó chấp nhận bất kỳ bộ chọn CSS / jQuery hợp lệ nào và trả về một đối tượng jQuery.

Sự khác biệt lớn nhất giữa các bộ sưu tập DOM tiêu chuẩn và các lựa chọn jQuery là các bộ sưu tập DOM thường hoạt động (không phải tất cả các phương thức đều trả về một bộ sưu tập trực tiếp), tức là bất kỳ thay đổi nào đối với DOM đều được phản ánh trong các bộ sưu tập nếu chúng bị ảnh hưởng. Chúng giống như một khung nhìn trên cây DOM, trong khi các lựa chọn jQuery là các ảnh chụp nhanh của cây DOM tại thời điểm hàm được gọi.

Tại sao console.log cũng hiển thị mảng các phần tử DOM bên cạnh chúng và chúng không phải là đối tượng và không phải là một mảng?

Các đối tượng jQuery là các đối tượng giống mảng , tức là chúng có các thuộc tính số và một thuộc tính length(hãy nhớ rằng các mảng chỉ là bản thân các đối tượng). Các trình duyệt có xu hướng hiển thị các mảng và các đối tượng giống mảng theo một cách đặc biệt, chẳng hạn như [ ... , ... , ... ].

Tất cả các "NodeLists" khó nắm bắt là gì và làm cách nào để chọn một?

Xem phần đầu tiên của câu trả lời của tôi. Bạn không thể chọn NodeList s, chúng là kết quả của một sự lựa chọn.

Theo như tôi biết, thậm chí không có cách nào để tạo NodeLists theo chương trình (tức là tạo một nút trống và thêm các nút sau này), chúng chỉ được trả về bởi một số phương thức / thuộc tính DOM.


2
@ user1032531: Chà, nếu bạn thực hiện bất kỳ thay đổi nào đối với một trong các phần tử DOM đã chọn (ví dụ: thêm một phần tử con), thì tất nhiên bạn sẽ thấy sự thay đổi vì đó là một phần tử DOM giống nhau. Tuy nhiên, giả sử bạn đã chọn tất cả các tdphần tử, việc thêm một tdphần tử mới sau này sẽ không tự động cập nhật lựa chọn để chứa phần tử mới.
Felix Kling

2
@FelixKling: Bạn nên đề cập rằng không phải tất cả các NodeLists đều được phát trực tiếp.
Bergi

2
Tôi muốn tất cả họ đều mảng
SuperUberDuper

7
Nó cũng có vẻ như phương pháp "chìa khóa", "mục" và "foreach" i trình bày trong NodeList, nhưng mất tích trong HTMLCollection
Krzysztof Grzybek

2
@KrzysztofGrzybek Đúng vậy và nó siêu khó chịu. Tại sao một trong số họ có .forEach()và cái kia không?
Robo Robok 24/03/18

30

0. Sự khác biệt giữa an HTMLCollectionvà a là NodeListgì?

Đây là một số định nghĩa dành cho bạn.

Thông số kỹ thuật DOM cấp 1 - Định nghĩa đối tượng khác :

Giao diện HTMLCollection

Bộ sưu tập HTMLC là một danh sách các nút. Một nút riêng lẻ có thể được truy cập bằng chỉ mục thứ tự hoặc tên hoặc thuộc tính id của nút. Lưu ý: Các tập hợp trong HTML DOM được coi là đang hoạt động nghĩa là chúng được cập nhật tự động khi tài liệu cơ bản được thay đổi.

Thông số DOM cấp 3 - NodeList

Giao diện NodeList

Giao diện NodeList cung cấp sự trừu tượng của một tập hợp các nút có thứ tự, mà không xác định hoặc hạn chế cách thực hiện tập hợp này. Các đối tượng NodeList trong DOM đang hoạt động.

Các mục trong NodeList có thể truy cập được thông qua một chỉ mục tích phân, bắt đầu từ 0.

Vì vậy, cả hai đều có thể chứa dữ liệu trực tiếp có nghĩa là DOM sẽ cập nhật khi giá trị của chúng thực hiện. Chúng cũng chứa một tập hợp các chức năng khác nhau.

Bạn sẽ lưu ý nếu bạn kiểm tra bảng điều khiển nếu bạn chạy các tập lệnh của mình mà tablephần tử DOM chứa cả a childNodes NodeList[2]và a children HTMLCollection[1]. Tại sao chúng khác nhau? Bởi vì HTMLCollectionchỉ có thể chứa các nút phần tử, NodeList cũng chứa một nút văn bản.

nhập mô tả hình ảnh ở đây

1. Sự khác biệt giữa document.getElementsByTagName("td")$("td")?

document.getElementsByTagName("td")lợi nhuận một loạt các yếu tố DOM (một NodeList), $("td")được gọi là một đối tượng jQuery trong đó có các yếu tố từ document.getElementsByTagName("td")trên thuộc tính của nó 0, 1, 2, vv Sự khác biệt chính là đối tượng jQuery là chậm hơn một chút để lấy nhưng cho phép truy cập vào tất cả các tiện dụng các hàm jQuery.

2. $("#myTable")$("td")là các đối tượng ( jQueryobject). Tại sao console.logcũng hiển thị mảng các phần tử DOM bên cạnh chúng và chúng không phải là đối tượng và không phải là mảng?

Họ là đối tượng với tài sản của họ 0, 1, 2vv thiết lập để các yếu tố DOM. Đây là một ví dụ đơn giản: về cách nó hoạt động:

jsFiddle

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

3. Tất cả các "NodeLists" khó nắm bắt là gì và làm cách nào để chọn một?

Bạn đã được lấy chúng trong mã của bạn, getElementsByClassNamegetElementsByTagNamecả hai trở lại NodeLists

NodeList


Bạn đã hiển thị DOM như thế nào trong phản hồi thứ 3 của mình? Cảm ơn!
user1032531

@ user1032531 đó là công cụ dành cho nhà phát triển Chrome. Nhân tiện tôi đã cập nhật phần bắt đầu của câu trả lời.
Daniel Imms

Nhật ký dạng mảng chủ yếu là kết quả của thuộc lengthtính, không phải của tên thuộc tính số. Và ví dụ của bạn về cảnh báo một chuỗi có liên quan gì console.log?
Bergi

Điều đó đã chỉ ra cách bạn có thể có các thuộc tính số trên các đối tượng. Tôi đang cố gắng nhấn mạnh sự thật rằng chúng là đối tượng, không phải mảng.
Daniel Imms

9

Ghi chú bổ sung

Sự khác biệt giữa HTMLCollection và NodeList là gì?

Bộ sưu tập HTMLC chỉ chứa các nút phần tử ( thẻ ) và một NodeList chứa tất cả các nút .

Có bốn loại nút:

  1. nút phần tử
  2. nút thuộc tính
  3. nút văn bản
  4. nút bình luận

nodeTypes

Khoảng trắng bên trong các phần tử được coi là văn bản và văn bản được coi là các nút.

Hãy xem xét những điều sau:

<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>

Khoảng trắng: <ul id="myList"> <li>List item</li></ul>

Không có khoảng trắng: <ul id="myList"><li>List item</li></ul>

Sự khác biệt giữa HTMLCollection và NodeList


2

$("td")là đối tượng jQuery mở rộng và nó có các phương thức jQuery, nó trả về đối tượng jquery chứa mảng các đối tượng html. document.getElementsByTagName("td")là phương thức js thô và trả về NodeList. Xem bài viết này


Cảm ơn Karaxuna. Vâng, tôi đã xem bài báo đó. Không biết nếu nó giúp, nhưng chắc chắn khiến tôi hỏi thêm :)
user1032531

Cảm ơn @karaxuna. Bài viết hữu ích, giải thích rất tốt.
Giuseppe

0

Các đối tượng NodeList là bộ sưu tập của Node, được trả về ví dụ như x. thuộc tính childNodes hoặc phương thức document.querySelectorAll () . Trong một số trường hợp, NodeList đang hoạt động , có nghĩa là các thay đổi trong DOM sẽ tự động cập nhật bộ sưu tập! Ví dụ: Node.childNodes đang hoạt động:

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.

Nhưng trong một số trường hợp khác, NodeList là tĩnh , nơi bất kỳ thay đổi nào trong DOM không ảnh hưởng đến nội dung của bộ sưu tập. querySelectorAll () trả về một NodeList tĩnh.

Các HTMLCollection là một live và ra lệnh cho bộ sưu tập của các yếu tố (nó sẽ tự động cập nhật khi tài liệu cơ bản được thay đổi). Nó có thể là kết quả của các thuộc tính như là con hoặc các phương thức như document.getElementsByTagName ()chỉ có thể có HTMLElement làm mục của chúng.

HTMLCollection cũng hiển thị các thành viên của nó trực tiếp dưới dạng tài sản theo cả tên và chỉ mục:

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

HTMLElement chỉ là một loại Nút:

Node << HTMLElement kế thừa

Node có thể là một số loại . Những điều quan trọng nhất như sau:

  • phần tử (1): Một nút Phần tử chẳng hạn như <p>hoặc <div>.
  • thuộc tính (2): Thuộc tính của một phần tử. Các thuộc tính phần tử không còn triển khai giao diện Node trong đặc tả DOM4!
  • text (3): Văn bản thực tế của Phần tử hoặc Thuộc tính.
  • comment (8): Một nút bình luận.
  • document (9): Một nút tài liệu.

Vì vậy, một sự khác biệt lớn là HTMLCollection chỉ chứa HTMLElements nhưng NodeList cũng chứa các nhận xét, văn bản khoảng trắng (ký tự xuống dòng, dấu cách ..), v.v. Kiểm tra nó như trong đoạn mã sau:

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>

Cả HTMLCollection và NodeList đều chứa thuộc tính độ dài mà bạn có thể sử dụng để lặp qua các mục của chúng. Không sử dụng for ... in hoặc for each ... in để liệt kê các mục trong NodeLists, vì chúng cũng sẽ liệt kê độ dài và thuộc tính mục và gây ra lỗi nếu tập lệnh của bạn giả định rằng nó chỉ phải xử lý các đối tượng phần tử. Ngoài ra, for..in không được đảm bảo sẽ truy cập các tài sản theo bất kỳ thứ tự cụ thể nào.

for (var i = 0; i < myNodeList.length; i++) {
  var item = myNodeList[i];
}

0

Đã có quá nhiều điều đã được nói, nhưng hãy nghĩ rằng một phiên bản câu trả lời tóm tắt hơn với một ví dụ để giải thích sự khác biệt giữa HTMLCollectionNodeListsẽ hữu ích.

Các loại nút trong DOM

  • Có 12 loại nút khác nhau, có thể có con của các loại nút khác nhau:

nhập mô tả hình ảnh ở đây

  • Chúng ta có thể sử dụng ba thuộc tính sau để kiểm tra và hỏi về các nút trong DOM:

    • nodeType Bất động sản
    • nodeName Bất động sản
    • nodeValue Bất động sản
  • Các nodeTypetài sản trả về kiểu nút, như một số, các nút chỉ định.

    • Nếu nút là một nút phần tử, thuộc nodeTypetính sẽ trả về 1 .
    • Nếu nút là một nút thuộc tính, thuộc nodeTypetính sẽ trả về 2 .
    • Nếu nút là nút văn bản, thuộc nodeTypetính sẽ trả về 3 .
    • Nếu nút là nút chú thích, thuộc nodeTypetính sẽ trả về 8 .
    • Thuộc tính này là chỉ đọc.

HTMLCollection so với NodeList

nhập mô tả hình ảnh ở đây

Chúng ta có thể hiểu sự khác biệt giữa HTMLCollectionNodeListrõ ràng hơn với ví dụ sau. Vui lòng thử kiểm tra kết quả đầu ra trong bảng điều khiển trình duyệt của riêng bạn để hiểu rõ hơn.

<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); 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.