모던 자바스크립트 Deep Dive, 이웅모
웹 페이지를 표시하기 위해 브라우저는 텍스트 문서인 HTML
, CSS
, JavaScript
를 파싱(parsing)하여 렌더링함
브라우저가 HTML 문서를 파싱하여 특징을 나타내고(프로퍼티) 이를 제어할 수 있는 API(메소드)를 제공하는 트리 자료구조
DOM은 아래와 같은 노드들로 구성되며 이런 노드 객체들은 자바스크립트 빌트인 객체가 아닌 브라우저 호스트 객체
그렇지만 자바스크립트 객체인 것은 맞으므로 프로토타입에 의한 상속구조를 가짐
→ 모든 노드 객체는 Object
> EventTarget
> Node
를 상속받음
문서 노드 Document
window.(생략가능)document
로 참조요소 노드 Element
어트리뷰트 노드 Attr
텍스트 노드 CharacterData
\n\r\t
들에 의해 생성div
등)HTMLCollection
(이후 설명) 객체로 반환, 없을 경우 빈 객체document
대신 특정 요소를 사용하면 Element.prototype.getElementsByTagName
메소드로 호출되며 해당 요소의 자식 노드 중에서 탐색 const $elems = document.getElementsByTagName('태그');
id
이용id
는 고유한 값이 원칙이나 여러 개가 있어도 오류X const $elem = document.getElementById('아이디');
class
이용HTMLCollection
(이후 설명) 객체로 반환, 없을 경우 빈 객체document
대신 특정 요소 사용시 HTML 태그를 이용했을 때와 동일하게 작용 const $elems = document.getElementsByClassName('아이디');
NodeList
(이후 설명) 객체 반환document
, 특정요소
모두 사용가능// 검색된 최초 노드만 반환
const $elem = document.querySeletor('CSS선택자');
// 검색된 모든 노드 반환
const $elem = document.querySeletorAll('CSS선택자');
Element.prototype.matches
메서드에 CSS 선택자를 인수로 주어 취득 여부를 확인 가능
Element
가 전달된 선택자로 취득 가능한지를 반환함
<body>
<ul id="order">
<li id="first">1번</li>
<li id="second">2번</li>
</ul>
</body>
<script>
const $list = document.querySelector('#first');
console.log($list.matches('ul > li#first')); // true
console.log($list.matches('ul > li#second')); // false
</script>
DOM API 호출 시 여러개의 결과값을 반환하기 위해 사용하는 DOM collection 객체
두 객체 모두 유사 배열 객체이면서 이터러블
다만 HTMLCollection의 경우 노드 객체의 상태변화를 실시간으로 반영하는 live 객체
NodeList의 경우 대부분의 경우 non-live 객체(live로 사용될 수도...)
따라서 HTMLCollection의 경우에는 인덱스를 이용하여 순차적으로 접근하면 노드 속성 변경에 따라 객체에서 제거될 수 있기 때문에 건너뛰는 노드가 생길 수 있음
NodeList의 경우도 live 객체로 동작하는 경우도 있음
∴ 그냥 안전하게 배열로 변환하여 사용하는 것이 좋음, 다양한 배열 메소드도 사용 가능
Array.from
, ...(스프레드문법)
등을 이용할 수 있음
Node
와 Element
의 차이는 탐색 시 자식 텍스트 노드의 포함 여부 (포함/미포함)
Node.prototype.childNodes
/ Element.prototype.children
Node.prototype.firstChild
/ Element.prototype.firstElementChild
Node.prototype.lastChild
/ Element.prototype.lastElementChild
자식노드의 존재를 확인하는 것은 Node.prototype.hasChildNodes
메소드
Element.prototype.children.length
, Element.prototype.childElementCount
값은 요소노드인 자식노드의 갯수만 확인할 수 있음
const $fruit = document.getElementById('fruit');
if( $fruit.hasChildNodes() ) {
if($fruit.childeElementCount === 0)
console.log('텍스트 노드만 있음');
else
console.log('요소 노드 존재');
}
Node.prototype.parentNode
사용하여 바로 위의 부모노드 탐색 가능
같은 부모를 둔 노드들에 대한 탐색을 진행
Node
와 Element
의 차이는 탐색시 형제 텍스트 노드의 포함 여부 (포함/미포함)
Node.prototype.previousSibling
/ Element.prototype.previousElementSibling
Node.prototype.nextSibling
/ Element.prototype.nextElementSibling