티스토리 뷰
오늘은 querySelectorAll나 getElementsByClassName과 같이 여러 개의 요소 노드 객체를 반환할 때 사용되는 객체인 HTMLCollection과 NodeList의 차이에 대해 다룰 것이다.
우선 둘의 공통점부터 살펴보자.
HTMLCollection과 NodeList는 모두 유사 배열 객체이면서 이터러블이다. 따라서 둘 다 length 프로퍼티를 가지기 때문에 객체를 배열처럼 접근할 수 있고 반복문을 돌릴 수 있다.
하지만 유사 배열 객체이기 때문에 자바스크립트에서 제공하는 배열 객체의 메소드를 사용할 수 없다는 특징이 있다. (ex. map, forEach, reduce 등등)
(유사 배열 객체에 대한 자세한 내용은 아래 링크에서 볼 수 있다.)
https://codingtoddlerr.tistory.com/101
HTMLCollection과 NodeList
메소드 | 의미 | 결과 |
document.getElementById('id') | HTML id속성으로 태그 선택하기 | id에 해당하는 태그 하나 |
document.getElementsByClassName('class') | HTML class속성으로 태그 선택하기 | class에 해당하는 태그 모음(HTMLCollection) |
document.getElementsByTagName('tag') | HTML 태그 이름으로 태그 선택하기 | tag에 해당하는 태그 모음(HTMLCollection) |
document.querySelector('css') | css 선택자로 태그 선택하기 | css 선택자에 해당하는 태그 중 가장 첫번째 태그 하나 |
document.querySelectorAll('css') | css 선택자로 태그 선택하기 | css 선택자에 해당하는 태그 모음(NodeList) |
- HTMLCollection 객체
HTMLCollection 객체는 getElementsByTagName과 getElementsByClassName 메서드가 반환한다.
HTMLCollection 객체는 노드 객체의 상태 변화를 실시간으로 반영하는 살아있는 live DOM 컬렉션 객체이다.
여기서 '살아있다' 라는 의미는 객체가 스스로 실시간 노드 객체의 상태 변경을 반영함을 의미한다.
- NodeList 객체
NodeList 객체는 querySelectorAll 등의 메서드가 반환한다.
NodeList 객체는 노드 객체의 상태 변화를 반영하지 않는 non-live DOM 컬렉션 객체이므로 HTMLCollection와 다르게 노드가 변경되어도 그 상태를 변경하지 않는다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTMLCollection vs NodeList</title>
</head>
<body>
<ul id="myList">
<li>Item 1</li>
<li>Item 2</li>
</ul>
<button id="addItem">Add Item</button>
<script>
const list = document.getElementById('myList');
// HTMLCollection
const itemsByTagName = list.getElementsByTagName('li');
console.log(itemsByTagName.length); // Output: 2
// NodeList
const itemsByQuerySelectorAll = document.querySelectorAll('#myList li');
console.log(itemsByQuerySelectorAll.length); // Output: 2
// Add Item
const addItemButton = document.getElementById('addItem');
addItemButton.addEventListener('click', function() {
const newItem = document.createElement('li');
newItem.textContent = 'New Item';
list.appendChild(newItem);
console.log(itemsByTagName.length); // Output: 3 (HTMLCollection는 실시간으로 노드 객체의 상태 변경을 반영한다.)
console.log(itemsByQuerySelectorAll.length); // Output: 2 (NodeList는 실시간으로 노드 객체의 상태 변경을 반영하지 않는다.)
});
</script>
</body>
</html>
위 예시를 보면 알 수 있듯이 HTMLCollection는 실시간으로 노드 객체의 상태 변경을 반영하지만 NodeList는 그렇지 않다.
하지만 childNodes 프로퍼티가 반환하는 NodeList 객체는 다르다.
HTMLCollection 객체와 같이 실시간으로 노드 객체의 상태 변경을 반영하는 live 객체로 동작한다.
또한 childeNodes는 요소 노드 뿐 만 아니라 공백 텍스트 노드(엔터 키)도 포함하고 있기 때문에 childNodes를 사용할 때 반환되는 NodeList 길이가 예상과 다를 수 있다. 아래 예시를 보면 childNodes를 사용했을 때 두 개의 요소 노드 (<p>)와 공백 텍스트 노드("Child 1"과 "Child 2" 사이의 공백), 총 3개의 노드가 반환된다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTMLCollection vs NodeList</title>
</head>
<body>
<div id="parent">
<p class="child">Child 1</p>
<p class="child">Child 2</p>
</div>
<script>
// HTMLCollection
const childrenByClass = document.getElementsByClassName('child');
console.log(childrenByClass.length); // Output: 2
const parent = document.getElementById('parent');
const childrenByTagName = parent.children;
console.log(childrenByTagName.length); // Output: 2
// NodeList
const nodeListByQuerySelectorAll = document.querySelectorAll('.child');
console.log(nodeListByQuerySelectorAll.length); // Output: 2
const nodeListByChildNodes = parent.childNodes;
console.log(nodeListByChildNodes.length); // Output: 3 (요소 노드 뿐 만 아니라 텍스트 노드도 포함되어 있다.)
</script>
</body>
</html>
또한, NodeList는 HTMCollection과 다르게 NodeList.prototype.forEach 메서드를 상속받아 사용할 수 있다. 그러나 forEach 외의 Array.prototype에서 제공하는 map, reduce, filter 등의 메서드는 사용할 수 없다.
따라서 HTMLCollection과 NodeList 모두 편리하게 사용하기 위해서는 배열로 만들어줘야 한다.
특히 HTMLCollection과 같은 live 객체는 반복문을 순회하면서 노드가 변경되는 경우, 개발자의 의도와는 다른 결과가 발생할 수 있으므로 배열로 바꾸어 사용하는 것이 바람직하다.
두 객체를 배열로 만드는 방법은 Array.from과 스프레트 연산자를 이용한 방법이 있다.
// Array.from() 사용 예제
const nodeList = document.querySelectorAll('.example');
const arrayFromNodeList = Array.from(nodeList);
// 스프레드 연산자 사용 예제
const nodeList = document.querySelectorAll('.example');
const arrayFromNodeList = [...nodeList];
둘 다 자주 사용되는 DOM 컬렉션 객체이므로 차이를 명확하게 알아두어야겠다.
'Language > JavaScript' 카테고리의 다른 글
[JavaScript] 요소의 속성 값을 가져오는 방법: getAttribute() (0) | 2024.03.23 |
---|---|
[JavaScript] 이벤트 버블링, 이벤트 캡처링, 이벤트 위임 (1) | 2024.03.23 |
[JavaScript] 동기와 비동기 (0) | 2023.08.16 |
[Javascript] 자바스크립트 드래그 앤 드롭 draggable (0) | 2023.07.29 |
[JavaScript] 무한 스크롤링 구현하기(fetch와 async/await) (0) | 2023.07.28 |
- Total
- Today
- Yesterday
- map
- Target
- javascript
- hydrationboundary
- CSS
- react
- currentTarget
- 유사배열객체
- 배열
- Next.js
- arguments
- 비동기
- 코드잇스프린트
- 중급 프로젝트
- innerhtml
- rest parameter
- 리액트
- html
- 프론트엔드
- tanstackquery
- Git
- 취업까지달린다
- 제어 컴포넌트
- 객체
- 동기
- 스프린트프론트엔드6기
- js
- GitHub
- 코드잇 스프린트
- 비제어 컴포넌트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |