
DOM은 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API트리 자료구조다.
노드 객체로 변환트리 자료 구조로 구성다음 HTML 문서를 렌더링 엔진인 파싱한다고 생각해보자

렌더링 엔진은 위 HTML 문서를 파싱하여 다음과 같이 DOM을 생성한다.

노드 객체는 상속 구조를 가지고 총 12개의 종류가 있다.
중요한 타입은 다음과 같이 4가지다.
1.문서 노드(document node)
2.요소 노드(element node)
3.어트리뷰트 노드(attribute node)
4.텍스트 노드(text node)
Object, EventTarget, Node 인터페이스를 상속한다.
DOM은 HTML 문서의 계층적 구조와 정보를 표현하는 것은 물론 노드 객체의 종류이다.→ 노드 타입에 따라 필요한 기능을 프로퍼티와 메서드의 집합인 **DOM API로 제공한다.**
→ 이 DOM API를 통해 HTML의 구조나 내용 또는 스타일 등을 동적으로 조작 가능하다.
Document.prototype.getElementById 메서드 사용한다.첫 번째 요소 노드만 반환한다.
Document.prototype/Element.prototype.getElementByTagName 메서드는 인수로 전달한 태그 이름을 갖는 모든 요소 노드들을 탐색하여 반환한다.
배열이나 객체와 같은 자료구조에 담아 반환해야 한다.Document.prototype/Element.prototype.getElementByClassName 메서드는 인수로 전달한 class 어트리뷰트 값이 갖는 모든 요소 노드들을 탐색하여 반환한다.
CSS 선택자는 스타일을 적용하고자 하는 HTML 요소를 특정할 때 사용하는 문법이다.

Document.prototype/Element.prototype.querySelecter메서드는 인수로 전달한 CSS선택자를 만족시키기는 하나의 요소 노드를 탐색하여 반환한다.CSS 선택자를 만족시키는 요소 노드가 여러 개인 경우 첫 번째 요소 노드만 반환한다.CSS 선택자를 만족시키는 요소 노드가 존재하지 않는 경우 null을 반환한다CSS 선택자가 문법에 맞지 않는 경우 DOMException 에러가 발생한다.Element.prototype.matches메서드는 인수로 전달한 CSS 선택자를 통해 특정 요소 노드를 취득할 수 있는지 확인한다.Element.prototype.matches메서드는 이벤트 위임을 사용할 때 유용하다.
HTMLCollection은 객체의 상태 변화를 실시간으로 반영한다.// class 값이 'red'인 요소 객체를 모두 HTMLCollection 으로 반환
const $elems = document.getElementsByClassName('red');// 객체 상태가 실시간으로 반영되면서 for문 으로 사용할 경우 원하는 대로 조작하기 어려움
// 배열로 변환해서 사용
[...$elems].forEach(ele => ele.className = 'blue');
NodeList.prototype.forEach 메서드를 상속 받아 사용할 수 있다.childNodes 프로퍼티가 반환하는 NodeList 객체는 HTMLCollection과 같이 상태가 실시간으로 반영한다노드 객체의 상태 변경과 상관없이 사용하려면 HTMLColleciton 이나 NodeList 객체를 배열로 변환해서 사용을 권장한다.
두 객체는 모두 유사 배열이면서 이터러블이다.
→ 스프레드 문법으로 배열로 변환 가능하다.
DOM 트리 상의 노드를 탐색할 수 있도록 Node,Element 인터페이스는 트리 탐색 프로퍼티를 제공한다.




Node.prototype.hasChildNodes메서드를 사용한다.true, 존재하지않으면 false를 반환한다.
firstChild 프로퍼티로 접근할 수 있다.
Node.prototype.parentNode프로퍼티를 사용한다.



nodeValue 참조하면 null 반환한다.<!DOCTYPE html>
<html>
<body>
<div id="foo">Hello</div>
</body>
<script>
<-- 1. #foo 요소 노드의 자식 노드인 텍스트 노드를 취득한다. -->
const $textNode = document.getElementById('foo').firstChild;
<-- 2. nodeValue 프로퍼티를 사용하여 텍스트 노드의 값을 변경한다. -->
$textNode.nodeValue = 'World';
</script>
</html>
textContent는 요소노드의 콘텐츠 영역(시작 태그와 종료태그 사이)의 모든 텍스트를 모두 반환한다.<!DOCTYPE html>
<html>
<body>
<div id="foo">Hello <span>world!</span></div>
</body>
<script>
// #foo 요소 노드의 텍스트를 모두 취득한다. 이때 HTML 마크업은 무시된다.
console.log(document.getElementById('foo').textContent); // Hello world!
</script>
</html>
HTML 마크업을 문자열로 반환innerHTML 프로퍼티에 문자열을 할당하면 요소노드의 모든 자식노드가 제거되고 할당한 문자열의 파싱되어 DOM에 반영<!DOCTYPE html>
<html>
<body>
<ul id="fruits">
<li class="apple">Apple</li>
</ul>
</body>
<script>
const $fruits = document.getElementById('fruits');
<-- 노드 추가 -->
$fruits.innerHTML += '<li class="banana">Banana</li>';
<-- 노드 교체 -->
$fruits.innerHTML = '<li class="orange">Orange</li>';
<-- 노드 삭제 -->
$fruits.innerHTML = '';
</script>
</html>
innerHTML 단점beforebegin, afterbegin, beforend, afterend)<!DOCTYPE html>
<html>
<body>
<!-- beforebegin -->
<div id="foo">
<!-- afterbegin -->
text
<!-- beforeend -->
</div>
<!-- afterend -->
</body>
</html>
Document.prototype.createElement(tagName) 메서드는 요소 노드를 생성하여 반환한다.tagName 인수에는 태그 이름을 나타내는 문자열을 전달한다.createElement 메서드로 생성한 요소 노드는 기존 DOM에 추가되지 않고 홀로 존재하는 상태로, 이후에 DOM에 추가하는 처리가 필요하다.createElement 메서드로 생성한 요소 노드는 아무런 자식 노드가 없는 상태이다.Document.prototype.createTextNode(text) 메서드는 텍스트 노드를 생성하여 반환한다.createTextNode 메서드로 생성한 텍스트 노드는 요소 노드의 자식 노드에 추가되지 않고 홀로 존재하는 상태로, 이후에 요소 노드에 추가하는 처리가 필요하다.Node.prototype.appendChild(childNode) 메서드는 인수로 전달한 노드를 메서드를 호출한 노드의 마지막 자식 노드로 추가한다.childNode 인수에는 추가할 자식 노드를 전달한다.textContent 프로퍼티를 사용하여 텍스트 노드를 추가하는 것이 더욱 간편하다.textContent 프로퍼티에 문자열을 할당하면 요소 노드의 모든 자식 노드가 제거되고 할당한 문자열이 텍스트로 추가되므로 주의!HTML 문서가 파싱 될 때 어티리뷰트는 어티리뷰트 노드로 변환 되어 요소 노드와 연결 된다.NamedNodeMap 객체에 담겨서 요소 노드의 attributes 프로퍼티에 저장한다.Element.prototype.getAttirbute(attributeName) : 어트리뷰트 값을 참조Element.prototype.setAttirbute(attributeName, attributeValue) : 어트리뷰트 값을 변경Element.prototype.hasAttirbute(attributeName) : 어트리뷰트 존재하는지 확인Element.prototype.removeAttirbute(attributeName) : 특정 어트리뷰트 삭제HTML 어트리 뷰트는 중복 관리 되는 것처럼 보인다.attributes 프로퍼티에서 관리하는 어트리뷰트 노드DOM 프로퍼티HTMLElement.prototype.style 프로퍼티getter / setter 가 모두 존재하는 접근자 프로퍼티로 요소 노드의 인라인 스타일을 취득하거나 추가 또는 변경한다.<!DOCTYPE html>
<html>
<body>
<div style="color: red">Hello World</div>
<script>
const $div = document.querySelector('div');
<-- 인라인 스타일 취득 -->
console.log($div.style); // CSSStyleDeclaration { 0: "color", ... }
<-- 인라인 스타일 변경 -->
$div.style.color = 'blue';
<-- 인라인 스타일 추가 -->
$div.style.width = '100px';
$div.style.height = '100px';
$div.style.backgroundColor = 'yellow';
</script>
</body>
</html>
DOM 프로퍼티는 class 가 아니라 className 과 classListElement.prototype.classNameclass 어트리뷰트의 값을 문자열로 반환한다.Element.prototype.classListclass 어트리뷰트의 정보를 담은 DOMTokenList 객체를 반환한다.DOMTokenList 객체는 class 어트리뷰트의 정보를나타내는 컬렉션 객체로 유사 배열이면서 이터러블DOMTokenList 주요 메서드add(... className) : 인수로 전달된 1개의 이상의 문자열을 class 어트리뷰트 값으로 추가remove(... className) : 인수로 전달한 1개 이상의 문자열과 일치하는 class 어트리뷰트에서 삭제한다.(일치 하는 클래스가 없으면 무시됨)item(index) : 인수로 전달한 index에 해당하는 클래스를 class 어트리뷰트에서 반환한다.contains(className) : 인수로 전달한 문자열과 일치하는 클래스가 class 어트리뷰트에 포함되어 있는지 확인한다.replace(oldClassName, newClassName) : 첫 번째 인수 클래스를 두번째 클래스로 변경한다.toggle(className[, force]) : 인수로 전달한 문자열과 일치하는 클래스가 존재하면 제거하고 존재하지 않으면 추가한다.