[JavaScript] DOM 탐색하기
DOM을 이용하면 요소와 요소의 콘텐츠에 무엇이든 할 수 있다.
하지만 무언가를 하기 전엔, 당연히 조작하고자 하는 DOM 객체에 접근하는 것이 선행되어야 한다.
DOM에서 수행하는 모든 연산은 document 객체에서 시작된다. document 객체는 DOM에 접근하기 위한 '진입점'인데, 진입점을 통과하면 어떤 노드에도 접근할 수 있다.
DOM 트리 상단의 노드들은 document가 제공하는 프로퍼티를 사용해 접근할 수 있다.
<html> = document.documentElement 이다.
document를 제외하고 DOM 트리 꼭대기에 있는 문서 노드는 <html> 태그에 해당하는 document.documentElement이다.<body> = document.body
document.body는 <body> 요소에 해당하는 DOM 노드로, 자주 쓰이는 노드 중 하나이다.
<head> = document.head
<head> 태그는 document.head로 접근할 수 있다.
2. childNodes, firstChild, lastChild로 자식노드 탐색하기
- 자식노드(child node, children)는 바로 아래의 자식 요소를 나타낸다. 자식 노드는 부모 노드의 바로 아래에서 중첩 관게를 만든다.
<head>와 <body>는 <html>요소의 자식노드이다. - 후손노드(descendants)는 중첩 관계에 있는 모든 요소를 의미한다. 자식노드, 자식 노드의 모든 자식 노드등이 후손 노드가 된다.
<html>
<body>
<div>시작</div>
<ul>
<li>항목</li>
</ul>
<div>끝</div>
<script>
for (let i = 0; i < document.body.childNodes.length; i++) {
alert( document.body.childNodes[i] );
}
</script>
...추가 내용...
</body>
</html>
//<div>나 <ul>같은 <body>의 자식 요소뿐만 아니라 <ul>의 자식 노드인 <li>와 <b>같이 더 깊은 곳에 있는 중첩 요소도 <body>의 후손 노드가 된다.
위의 예시를 실행하면 document.body의 자식요소들이 출력되는데, 흥미로운 점은 마지막에 <script>가 출력된다. <script>아래 더 많은 (추가내용...)들이 있지만, 스크립트 실행 시점엔 브라우저가 추가 내용은 읽지 못한 상태이기 때문에 스크립트 역시 추가 나용을 보지 못해서 이런 결과가 나타난 것이다.
firstChild와 lastChild 프로퍼티를 이용하면 첫 번쨰, 마지막 자식 노드에 빠르게 접근할 수 있다.
elem.childNodes[0] === elem.firstChild
elem.childNodes[elem.childNodes.length - 1] === elem.lastChild
참고로 자식 노드의 존재 여부를 검사할 땐 함수 elem.hasChildNodes()를 사용할 수도 있다.
3. DOM 컬렉션
위에서 살펴본 childNodes난 마치 배열같아 보이지만, childNodes는 배열이 아닌 반복가능한 유사 배열 객체인 컬렉션(collection)이다.
그래서 아래와 같은 특징을 가진다.
- for...of 를 사용할 수 있다.
for (let node of document.body.childNodes) {
alert(node);
}
// 컬렉션 내의 모든 노드를 보여준다.
- 배열이 아니기 때문에 배열 메서드를 쓸 수 없다.
alert(document.body.childNodes.filter);
// undefined (filter 메서드가 없습니다.)
4. 형제와 부모 노드
같은 부모를 가진 노드는 형제(sibling)노드 라고 부른다.
<head>와 <body>는 대표적인 형제 노드이다.
<html>
<head>...</head><body>...</body>
</html>
- <body>는 <head>의 ‘다음(next)’ 혹은 '우측(right)'에 있는 형제 노드
- <head>는 <body>의 ‘이전(previous)’ 혹은 '좌측(left)'에 있는 형제 노드
다음 형제 노드에 대한 정보는 nextSibling, 이전 형제 노드에 대한 정보는 previousSibling 프로퍼티에서 찾을 수 있고,
부모 노드에 대한 정보는 parentNode 프로퍼티를 이용해 참조할 수 있다.
// <body>의 부모 노드는 <html>
alert( document.body.parentNode === document.documentElement ); // true
// <head>의 다음 형제 노드는 <body>
alert( document.head.nextSibling ); // HTMLBodyElement
// <body>의 이전 형제 노드는 <head>
alert( document.body.previousSibling ); // HTMLHeadElement