[JavaScript] DOM과 자바스크립트

zmin·2022년 5월 4일
0

모던 자바스크립트 Deep Dive, 이웅모

브라우저의 렌더링

웹 페이지를 표시하기 위해 브라우저는 텍스트 문서인 HTML, CSS, JavaScript를 파싱(parsing)하여 렌더링함

DOM(Document Object Model)

브라우저가 HTML 문서를 파싱하여 특징을 나타내고(프로퍼티) 이를 제어할 수 있는 API(메소드)를 제공하는 트리 자료구조

DOM은 아래와 같은 노드들로 구성되며 이런 노드 객체들은 자바스크립트 빌트인 객체가 아닌 브라우저 호스트 객체
그렇지만 자바스크립트 객체인 것은 맞으므로 프로토타입에 의한 상속구조를 가짐

→ 모든 노드 객체는 Object > EventTarget > Node를 상속받음

  • 문서 노드 Document

    • DOM트리의 최상단에 있는 루트 노드, 하나의 HTML문서 당 하나
    • 아래 서술될 노드들이 모두 이 문서 노드의 자식 노드 이므로 접근을 위해서는 이 문서 노드를 꼭 거쳐야 함
    • 브라우저 상 전역객체인 window의 document 프로퍼티에 바인딩 되어있어
      window.(생략가능)document로 참조
  • 요소 노드 Element

    • 문서의 구조 표현
  • 어트리뷰트 노드 Attr

    • HTML 요소의 어트리뷰트 정보들을 포함하고 있는 객체
    • 해당 요소 노드에 연결 되어있음
      따라서 어트리뷰트 노드에 접근하려면 먼저 요소 노드 접근이 필수적
  • 텍스트 노드 CharacterData

    • HTML 요소의 텍스트 컨텐츠를 가리키는 객체
    • 자식노드 없음, 리프 노드
    • 공백 텍스트 노드
      • HTML요소 사이의 공백문자 \n\r\t 들에 의해 생성
      • 특별한 역할을 하진 않지만 노드 탐색시 주의해야함

요소 노드 취득

HTML 태그(div 등)

  • 모든 요소를 찾아서 HTMLCollection(이후 설명) 객체로 반환, 없을 경우 빈 객체
  • document 대신 특정 요소를 사용하면 Element.prototype.getElementsByTagName 메소드로 호출되며 해당 요소의 자식 노드 중에서 탐색
  const $elems = document.getElementsByTagName('태그');

id 이용

  • 단 하나의 요소만 반환하며 없을 경우 null
  • 원래 id는 고유한 값이 원칙이나 여러 개가 있어도 오류X
    가장 첫 번째 요소 반환
  const $elem = document.getElementById('아이디');

class 이용

  • 모든 요소를 찾아서 HTMLCollection(이후 설명) 객체로 반환, 없을 경우 빈 객체
  • document대신 특정 요소 사용시 HTML 태그를 이용했을 때와 동일하게 작용
  const $elems = document.getElementsByClassName('아이디');

CSS 선택자 이용

  • CSS에서 HTML 요소를 선택할 때 사용하는 문법을 그대로 사용하여 요소 취득
  • 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>

HTMLCollection, NodeList

DOM API 호출 시 여러개의 결과값을 반환하기 위해 사용하는 DOM collection 객체
두 객체 모두 유사 배열 객체이면서 이터러블
다만 HTMLCollection의 경우 노드 객체의 상태변화를 실시간으로 반영하는 live 객체
NodeList의 경우 대부분의 경우 non-live 객체(live로 사용될 수도...)

따라서 HTMLCollection의 경우에는 인덱스를 이용하여 순차적으로 접근하면 노드 속성 변경에 따라 객체에서 제거될 수 있기 때문에 건너뛰는 노드가 생길 수 있음

NodeList의 경우도 live 객체로 동작하는 경우도 있음

∴ 그냥 안전하게 배열로 변환하여 사용하는 것이 좋음, 다양한 배열 메소드도 사용 가능
Array.from, ...(스프레드문법) 등을 이용할 수 있음

노드 탐색

자식 노드

NodeElement의 차이는 탐색 시 자식 텍스트 노드의 포함 여부 (포함/미포함)

  • Node.prototype.childNodes / Element.prototype.children
    • 탐색되는 자식 노드들을 담은 NodeList / HTMLCollection 반환
  • 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 사용하여 바로 위의 부모노드 탐색 가능

형제 노드

같은 부모를 둔 노드들에 대한 탐색을 진행
NodeElement의 차이는 탐색시 형제 텍스트 노드의 포함 여부 (포함/미포함)

  • Node.prototype.previousSibling / Element.prototype.previousElementSibling
    • 현재 노드보다 이전에 있는 형제노드 반환
  • Node.prototype.nextSibling / Element.prototype.nextElementSibling
    • 현재 노드보다 이후에 있는 형제노드 반환
profile
308 Permanent Redirect

0개의 댓글