DOM은 HTML λ¬Έμ„œμ˜ 계측적 ꡬ쑰와 정보λ₯Ό ν‘œν˜„ν•˜λ©° 이λ₯Ό μ œμ–΄ν•  수 μžˆλŠ” API, 즉 ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•˜λŠ” μžλ£Œκ΅¬μ‘°λ‹€.


🌺 39.1 λ…Έλ“œ

βœ” 39.1.1 HTML μš”μ†Œμ™€ λ…Έλ“œ 객체

HTML μš”μ†ŒλŠ” λ Œλ”λ§ 엔진에 μ˜ν•΄ νŒŒμ‹±λ˜μ–΄ DOM을 κ΅¬μ„±ν•˜λŠ” μš”μ†Œ λ…Έλ“œ 객체둜 λ³€ν™˜λœλ‹€. μ΄λ•Œ HTML μš”μ†Œμ˜ μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œλ‘œ, HTML μš”μ†Œμ˜ ν…μŠ€νŠΈ μ½˜ν…μΈ λŠ” ν…μŠ€νŠΈ λ…Έλ“œλ‘œ λ³€ν™˜λœλ‹€. HTML μš”μ†ŒλŠ” 쀑첩 관계λ₯Ό κ°–λŠ”λ° 이둜 인해 μš”μ†Œκ°„ 계측적인 λΆ€μž 관계가 ν˜•μ„±λœλ‹€. μ΄λŸ¬ν•œ HTMl μš”μ†Œκ°„μ˜ λΆ€μž 관계λ₯Ό λ°˜μ˜ν•˜μ—¬ HTMl λ¬Έμ„œμ˜ ꡬ성 μš”μ†ŒμΈ HTMl μš”μ†Œλ₯Ό κ°μ²΄ν™”ν•œ λͺ¨λ“  λ…Έλ“œ 객체듀을 트리 자료 ꡬ쑰둜 κ΅¬μ„±ν•œλ‹€.

  • 트리 자료ꡬ쑰 트리 μžλ£Œκ΅¬μ‘°λŠ” λΆ€λͺ¨ λ…Έλ“œμ™€ μžμ‹ λ…Έλ“œλ‘œ κ΅¬μ„±λ˜μ–΄ λ…Έλ“œ κ°„μ˜ 계측적 ꡬ쑰(λΆ€μž, ν˜•μ œ 관계)λ₯Ό ν‘œν˜„ν•˜λŠ” λΉ„μ„ ν˜• 자료ꡬ쑰λ₯Ό λ§ν•œλ‹€. 트리 μžλ£Œκ΅¬μ‘°λŠ” λΆ€λͺ¨ λ…Έλ“œκ°€ μ—†λŠ” ν•˜λ‚˜μ˜ μ΅œμƒμœ„ λ…Έλ“œ(루트 λ…Έλ“œ) μ—μ„œ μ‹œμž‘ν•œλ‹€. 루트 λ…Έλ“œλŠ” 0개 μ΄μƒμ˜ μžμ‹ λ…Έλ“œλ₯Ό κ°–λŠ”λ‹€. μžμ‹ λ…Έλ“œκ°€ μ—†λŠ” λ…Έλ“œλ₯Ό 리프 λ…Έλ“œλΌ ν•œλ‹€. λ…Έλ“œ κ°μ²΄λ“€λ‘œ κ΅¬μ„±λœ 트리 자료ꡬ쑰λ₯Ό DOM (Document Object Model)이라고 ν•œλ‹€.

βœ” 39.1.2 λ…Έλ“œ 객체의 νƒ€μž…

DOM의 λ…Έλ“œ κ°μ²΄λŠ” μ’…λ₯˜κ°€ 있고 상속 ꡬ쑰λ₯Ό κ°–λŠ”λ‹€. λ…Έλ“œ κ°μ²΄λŠ” 총 12개의 μ’…λ₯˜(λ…Έλ“œ νƒ€μž…)κ°€ μžˆλ‹€.

  • λ¬Έμ„œ λ…Έλ“œ λ¬Έμ„œ λ…Έλ“œλŠ” DOM 트리의 μ΅œμƒμœ„μ— μ‘΄μž¬ν•˜λŠ” 루트 λ…Έλ“œλ‘œμ„œ document 객체λ₯Ό 가리킨닀. document κ°μ²΄λŠ” λΈŒλΌμš°μ €κ°€ λ Œλ”λ§ν•œ HTML λ¬Έμ„œ 전체λ₯Ό κ°€λ¦¬ν‚€λŠ” κ°μ²΄λ‘œμ„œ μ „μ—­ 객체 window의 document ν”„λ‘œνΌν‹°μ— 바인딩 λ˜μ–΄μžˆλ‹€. HTML λ¬Έμ„œλ‹Ή document κ°μ²΄λŠ” μœ μΌν•˜λ‹€. λ¬Έμ„œ λ…Έλ“œλŠ” DOM 트리의 루트 λ…Έλ“œμ΄λ―€λ‘œ μš”μ†Œ, μ–΄νŠΈλ¦¬λ·°νŠΈ, ν…μŠ€νŠΈ λ…Έλ“œμ— μ ‘κ·Όν•˜λ €λ©΄ λ¬Έμ„œ λ…Έλ“œλ₯Ό 톡해야 ν•œλ‹€.
  • μš”μ†Œ λ…Έλ“œ μš”μ†Œ λ…Έλ“œλŠ” HTML μš”μ†Œλ₯Ό κ°€λ¦¬ν‚€λŠ” 객체둜 HTML μš”μ†Œ κ°„μ˜ 쀑첩에 μ˜ν•΄ λΆ€μž 관계λ₯Ό 가지며 이 λΆ€μž 관계λ₯Ό 톡해 정보λ₯Ό κ΅¬μ‘°ν™”ν•œλ‹€.
  • μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œ μ–΄νŠΈλ¦¬ 뷰트 λ…Έλ“œλŠ” HTMl μš”μ†Œμ˜ μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό κ°€λ¦¬ν‚€λŠ” 객체둜 μ–΄νŠΈλ¦¬λ·°νŠΈκ°€ μ§€μ •λœ HTML μš”μ†Œμ˜ μš”μ†Œ λ…Έλ“œμ™€ μ—°κ²°λ˜μ–΄ μžˆλ‹€. μ–΄νŠΈλ¦¬ λ·°νŠΈλŠ” λΆ€λͺ¨ λ…Έλ“œμ™€ μ—°κ²°λ˜μ–΄μžˆμ§€ μ•Šλ‹€. λ”°λΌμ„œ μš”μ†Œλ…Έλ“œμ˜ ν˜•μ œλ…Έλ“œκ°€ 될수 μ—†λ‹€. λ”°λΌμ„œ μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œμ— μ ‘κ·Όν•˜μ—¬ μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό μ°Έμ‘°ν•˜κ±°λ‚˜ λ³€κ²½ν•˜λ €λ©΄ λ¨Όμ € μš”μ†Œ λ…Έλ“œμ— μ ‘κ·Όν•΄μ•Ό ν•œλ‹€.
  • ν…μŠ€νŠΈ λ…Έλ“œ ν…μŠ€νŠΈ λ…Έλ“œλŠ” HTML μš”μ†Œμ˜ ν…μŠ€νŠΈν‹€ κ°€λ¦¬ν‚€λŠ” 객체둜 μš”μ†Œλ…Έλ“œκ°€ λ¬Έμ„œμ˜ ꡬ쑰λ₯Ό ν‘œν˜„ν•œλ‹€λ©΄ ν…μŠ€νŠΈ λ…Έλ“œλŠ” λ¬Έμ„œμ˜ 정보λ₯Ό ν‘œν˜„ν•œλ‹€κ³  ν•  수 μžˆλ‹€. ν…μŠ€νŠΈ λ…Έλ“œλŠ” μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμ΄λ©° 리프 λ…Έλ“œμ΄λ‹€.

βœ” 39.1.3 λ…Έλ“œ 객체의 상속 ꡬ쑰

DOM을 κ΅¬μ„±ν•˜λŠ” λ…Έλ“œ κ°μ²΄λŠ” μžμ‹ μ˜ ꡬ쑰와 정보λ₯Ό μ œμ–΄ν•  수 μžˆλŠ” DOM APIλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€. DOM을 κ΅¬μ„±ν•˜λŠ” λ…Έλ“œ κ°μ²΄λŠ” ECMAScript 사양에 μ •μ˜λœ ν‘œμ€€ 빌트인 객체가 μ•„λ‹ˆλΌ λΈŒλΌμš°μ € ν™˜κ²½μ—μ„œ μΆ”κ°€μ μœΌλ‘œ μ œκ³΅ν•˜λŠ” 호슀트 객체닀. ν•˜μ§€λ§Œ λ…Έλ“œ 객체도 μžλ°”μŠ€ν¬λ¦½νŠΈ κ°μ²΄μ΄λ―€λ‘œ ν”„λ‘œν† νƒ€μž…μ— μ˜ν•œ 상속 ꡬ쑰λ₯Ό κ°–λŠ”λ‹€. λ…Έλ“œ 객체의 μƒμ†κ΅¬μ‘°λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

배열이 객체인 λ™μ‹œμ— 배열인 κ²ƒμ²˜λŸΌ input μš”μ†Œ λ…Έλ“œ 객체도 λ‹€μŒκ³Ό 같이 λ‹€μ–‘ν•œ νŠΉμ„±μ„ κ°–λŠ” 객체이며, μ΄λŸ¬ν•œ νŠΉμ„±μ„ λ‚˜νƒ€λ‚΄λŠ” κΈ°λŠ₯듀을 상속을 톡해 μ œκ³΅λ°›λŠ”λ‹€.

λ…Έλ“œ 객체의 상속 κ΅¬μ‘°λŠ” 개발자 λ„κ΅¬μ˜ Elements νŒ¨λ„ 우츑의 Properties νŒ¨λ„μ—μ„œ 확인할 수 μžˆλ‹€.

μ •λ¦¬ν•˜μžλ©΄, DOM은 HTML λ¬Έμ„œμ˜ 계측적 ꡬ쑰와 정보λ₯Ό ν‘œν˜„ν•˜λŠ” 것은 λ¬Όλ‘  λ…Έλ“œ 객체의 μ’…λ₯˜, 즉 λ“œ νƒ€μž…μ— 따라 ν•„μš”ν•œ κΈ°λŠ₯을 ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œμ˜ 집합인 DOM API둜 μ œκ³΅ν•œλ‹€. 이 DOM APIλ₯Ό 톡해 HTML의 κ΅¬μ‘°λ‚˜ λ‚΄μš© λ˜λŠ” μŠ€νƒ€μΌ 등을 λ™μ μœΌλ‘œ μ‘°μž‘ν•  수 μžˆλ‹€.


🌺 39.2 μš”μ†Œ λ…Έλ“œ 취득

HTML의 κ΅¬μ‘°λ‚˜ λ‚΄μš© λ˜λŠ” μŠ€νƒ€μΌ 등을 λ™μ μœΌλ‘œ μ‘°μž‘ν•˜λ €λ©΄ λ¨Όμ € μš”μ†Œ λ…Έλ“œλ₯Ό 취득해야 ν•œλ‹€. ν…μŠ€νŠΈ λ…Έλ“œλŠ” μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμ΄κ³ , μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œλŠ” μš”μ†Œ λ…Έλ“œμ™€ μ—°κ²°λ˜μ–΄ 있기 λ•Œλ¬Έμ΄λ‹€. λ”°λΌμ„œ DOM은 μš”μ†Œ λ…Έλ“œλ₯Ό 취득할 수 μžˆλŠ” λ‹€μ–‘ν•œ λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•œλ‹€.

βœ” 39.2.1 idλ₯Ό μ΄μš©ν•œ μš”μ†Œ λ…Έλ“œ 취득 : getElementById

Document.prototype.getElementById λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬ν•œ id μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 κ°–λŠ” ν•˜λ‚˜μ˜ μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€. getElementByIdλ©”μ„œλ“œλŠ” Document.prototype의 ν”„λ‘œνΌν‹°λ‹€. λ”°λΌμ„œ λ°˜λ“œμ‹œ λ¬Έμ„œ λ…Έλ“œμΈ documentλ₯Ό 톡해 ν˜ΈμΆœν•΄μ•Όν•œλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul>
      <li id="apple">Apple</li>
      <li id="banana">Banana</li>
      <li id="orange">Orange</li>
    </ul>
    <script>
      // id 값이 'banana'인 μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€.
      // 두 번째 li μš”μ†Œκ°€ νŒŒμ‹±λ˜μ–΄ μƒμ„±λœ μš”μ†Œ λ…Έλ“œκ°€ λ°˜ν™˜λœλ‹€.
      const $elem = document.getElementById('banana');

      // μ·¨λ“ν•œ μš”μ†Œ λ…Έλ“œμ˜ style.color ν”„λ‘œνΌν‹° 값을 λ³€κ²½ν•œλ‹€.
      $elem.style.color = 'red';
    </script>
  </body>
</html>

id 값은 HTML λ¬Έμ„œ λ‚΄μ—μ„œ μœ μΌν•œ 값이어야 ν•˜λ©°, class μ–΄νŠΈλ¦¬λ·°νŠΈμ™€λŠ” 달리 곡백 문자둜 κ΅¬λΆ„ν•˜μ—¬ μ—¬λŸ¬ 개의 값을 κ°€μ§ˆ 수 μ—†λ‹€. 단, HTML λ¬Έμ„œ 내에 μ€‘λ³΅λœ id값을 κ°–λŠ” HTML μš”μ†Œκ°€ μ—¬λŸ¬ 개 μ‘΄μž¬ν•˜λ”λΌλ„ μ–΄λ– ν•œ μ—λŸ¬λ„ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

HTML μš”μ†Œμ— id μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό λΆ€μ—¬ν•˜λ©΄ id κ°’κ³Ό λ™μΌν•œ μ΄λ¦„μ˜ μ „μ—­ λ³€μˆ˜κ°€ μ•”λ¬΅μ μœΌλ‘œ μ„ μ–Έλ˜κ³  ν•΄λ‹Ή λ…Έλ“œ 객체가 ν• λ‹Ήλ˜λŠ” λΆ€μˆ˜ νš¨κ³Όκ°€ μžˆλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <div id="foo"></div>
    <script>
      // id κ°’κ³Ό λ™μΌν•œ μ΄λ¦„μ˜ μ „μ—­ λ³€μˆ˜κ°€ μ•”λ¬΅μ μœΌλ‘œ μ„ μ–Έλ˜κ³  ν•΄λ‹Ή λ…Έλ“œ 객체가 ν• λ‹Ήλœλ‹€.
      console.log(foo === document.getElementById('foo')); // true

      // 암묡적 μ „μ—­μœΌλ‘œ μƒμ„±λœ μ „μ—­ ν”„λ‘œνΌν‹°λŠ” μ‚­μ œλ˜μ§€λ§Œ μ „μ—­ λ³€μˆ˜λŠ” μ‚­μ œλ˜μ§€ μ•ŠλŠ”λ‹€.
      delete foo;
      console.log(foo); // <div id="foo"></div>
    </script>
  </body>
</html>

βœ” 39.2.2 νƒœκ·Έ 이름을 μ΄μš©ν•œ μš”μ†Œ λ…Έλ“œ 취득 : getElementsByTagName

Document.prototype/Element.prototype.getElementByTagName λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬ν•œ νƒœκ·Έ 이름을 κ°–λŠ” λͺ¨λ“  μš”μ†Œ λ…Έλ“œλ“€μ„ νƒμƒ‰ν•˜μ—¬ HTMLCollection 객체둜 λ°˜ν™˜ν•œλ‹€. HTMLCollection κ°μ²΄λŠ” μœ μ‚¬ λ°°μ—΄ κ°μ²΄μ΄λ©΄μ„œ μ΄ν„°λŸ¬λΈ”μ΄λ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li>Apple</li>
      <li>Banana</li>
      <li>Orange</li>
    </ul>
    <ul>
      <li>HTML</li>
    </ul>
    <script>
      // DOM μ „μ²΄μ—μ„œ νƒœκ·Έ 이름이 li인 μš”μ†Œ λ…Έλ“œλ₯Ό λͺ¨λ‘ νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€.
      const $lisFromDocument = document.getElementsByTagName('li');
      console.log($lisFromDocument); // HTMLCollection(4) [li, li, li, li]

      // #fruits μš”μ†Œμ˜ μžμ† λ…Έλ“œ μ€‘μ—μ„œ νƒœκ·Έ 이름이 li인 μš”μ†Œ λ…Έλ“œλ₯Ό λͺ¨λ‘
      // νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€.
      const $fruits = document.getElementById('fruits');
      const $lisFromFruits = $fruits.getElementsByTagName('li');
      console.log($lisFromFruits); // HTMLCollection(3) [li, li, li]
    </script>
  </body>
</html>

getElementsByTagName λ©”μ„œλ“œλŠ” Document.prototype에 μ •μ˜λœ λ©”μ„œλ“œμ™€ Element.prototype에 μ •μ˜λœ λ©”μ„œλ“œκ°€ μžˆλŠ”λ° Document.prototype.getElementsByTagNameλ©”μ„œλ“œλŠ” documentλ₯Ό 톡해 ν˜ΈμΆœν•˜λ©° DOM μ „μ²΄μ—μ„œ μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€.

ν•˜μ§€λ§Œ Element.prototype.getElementsByTagName @ λ©”μ„œλ“œλŠ” νŠΉμ • μš”μ†Œ λ…Έλ“œλ₯Ό 톡해 ν˜ΈμΆœν•˜λ©°, νŠΉμ • μš”μ†Œ λ…Έλ“œμ˜ μžμ† λ…Έλ“œ μ€‘μ—μ„œ μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€.

βœ” 39.2.3 classλ₯Ό μ΄μš©ν•œ μš”μ†Œ λ…Έλ“œ 취득 : getElementsByClassName

Document.prototype/Element.prototype.getElementsByClassName λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬ν•œ class μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 κ°–λŠ” λͺ¨λ“  μš”μ†Œ λ…Έλ“œλ“€μ„ νƒμƒ‰ν•˜μ—¬ HTMLCollection 객체둜 λ°˜ν™˜ν•œλ‹€

<!DOCTYPE html>
<html>
  <body>
    <ul>
      <li class="fruit apple">Apple</li>
      <li class="fruit banana">Banana</li>
      <li class="fruit orange">Orange</li>
    </ul>
    <script>
      // class 값이 'fruit'인 μš”μ†Œ λ…Έλ“œλ₯Ό λͺ¨λ‘ νƒμƒ‰ν•˜μ—¬ HTMLCollection 객체에 λ‹΄μ•„ λ°˜ν™˜ν•œλ‹€.
      const $elems = document.getElementsByClassName('fruit');

      // μ·¨λ“ν•œ λͺ¨λ“  μš”μ†Œμ˜ CSS color ν”„λ‘œνΌν‹° 값을 λ³€κ²½ν•œλ‹€.
      [...$elems].forEach(elem => { elem.style.color = 'red'; });

      // class 값이 'fruit apple'인 μš”μ†Œ λ…Έλ“œλ₯Ό λͺ¨λ‘ νƒμƒ‰ν•˜μ—¬ HTMLCollection 객체에 λ‹΄μ•„ λ°˜ν™˜ν•œλ‹€.
      const $apples = document.getElementsByClassName('fruit apple');

      // μ·¨λ“ν•œ λͺ¨λ“  μš”μ†Œ λ…Έλ“œμ˜ style.color ν”„λ‘œνΌν‹° 값을 λ³€κ²½ν•œλ‹€.
      [...$apples].forEach(elem => { elem.style.color = 'blue'; });
    </script>
  </body>
</html>

βœ” 39.2.4 css μ„ νƒμžλ₯Ό μ΄μš©ν•œ μš”μ†Œ λ…Έλ“œ 취득 : querySelector/querySelectorAll

CSS μ„ νƒμžλŠ” μŠ€νƒ€μΌμ„ μ μš©ν•˜κ³ μž ν•˜λŠ” HTML μš”μ†Œλ₯Ό νŠΉμ •ν•  λ•Œ μ‚¬μš©ν•˜λŠ” 문법이닀.

/* 전체 μ„ νƒμž: λͺ¨λ“  μš”μ†Œλ₯Ό 선택 */
* { ... }
/* νƒœκ·Έ μ„ νƒμž: λͺ¨λ“  p νƒœκ·Έ μš”μ†Œλ₯Ό λͺ¨λ‘ 선택 */
p { ... }
/* id μ„ νƒμž: id 값이 'foo'인 μš”μ†Œλ₯Ό λͺ¨λ‘ 선택 */
#foo { ... }
/* class μ„ νƒμž: class 값이 'foo'인 μš”μ†Œλ₯Ό λͺ¨λ‘ 선택 */
.foo { ... }
/* μ–΄νŠΈλ¦¬λ·°νŠΈ μ„ νƒμž: input μš”μ†Œ 쀑에 type μ–΄νŠΈλ¦¬λ·°νŠΈ 값이 'text'인 μš”μ†Œλ₯Ό λͺ¨λ‘ 선택 */
input[type=text] { ... }
/* 후손 μ„ νƒμž: div μš”μ†Œμ˜ 후손 μš”μ†Œ 쀑 p μš”μ†Œλ₯Ό λͺ¨λ‘ 선택 */
div p { ... }
/* μžμ‹ μ„ νƒμž: div μš”μ†Œμ˜ μžμ‹ μš”μ†Œ 쀑 p μš”μ†Œλ₯Ό λͺ¨λ‘ 선택 */
div > p { ... }
/* 인접 ν˜•μ œ μ„ νƒμž: p μš”μ†Œμ˜ ν˜•μ œ μš”μ†Œ 쀑에 p μš”μ†Œ λ°”λ‘œ 뒀에 μœ„μΉ˜ν•˜λŠ” ul μš”μ†Œλ₯Ό 선택 */
p + ul { ... }
/* 일반 ν˜•μ œ μ„ νƒμž: p μš”μ†Œμ˜ ν˜•μ œ μš”μ†Œ 쀑에 p μš”μ†Œ 뒀에 μœ„μΉ˜ν•˜λŠ” ul μš”μ†Œλ₯Ό λͺ¨λ‘ 선택 */
p ~ ul { ... }
/* 가상 클래슀 μ„ νƒμž: hover μƒνƒœμΈ a μš”μ†Œλ₯Ό λͺ¨λ‘ 선택 */
a:hover { ... }
/* 가상 μš”μ†Œ μ„ νƒμž: p μš”μ†Œμ˜ μ½˜ν…μΈ μ˜ μ•žμ— μœ„μΉ˜ν•˜λŠ” 곡간을 선택
   일반적으둜 content ν”„λ‘œνΌν‹°μ™€ ν•¨κ»˜ μ‚¬μš©λœλ‹€. */
p::before { ... }

Document.prototype/Select.prototype.querySelector λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬ν•œ CSS μ„ νƒμžλ₯Ό λ§Œμ‘±μ‹œν‚€λŠ” ν•˜λ‚˜μ˜ μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul>
      <li class="apple">Apple</li>
      <li class="banana">Banana</li>
      <li class="orange">Orange</li>
    </ul>
    <script>
      // class μ–΄νŠΈλ¦¬λ·°νŠΈ 값이 'banana'인 첫 번째 μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€.
      const $elem = document.querySelector('.banana');

      // μ·¨λ“ν•œ μš”μ†Œ λ…Έλ“œμ˜ style.color ν”„λ‘œνΌν‹° 값을 λ³€κ²½ν•œλ‹€.
      $elem.style.color = 'red';
    </script>
  </body>
</html>
  • 인수둜 μ „λ‹¬ν•œ CSS μ„ νƒμžλ₯Ό λ§Œμ‘±μ‹œν‚€λŠ” μš”μ†Œ λ…Έλ“œκ°€ μ—¬λŸ¬ 개인 경우 첫 번째 μš”μ†Œ λ…Έλ“œλ§Œ λ°˜ν™˜
  • 인수둜 μ „λ‹¬ν•œ CSS μ„ νƒμžλ₯Ό λ§Œμ‘±μ‹œν‚€λŠ” μš”μ†Œ λ…Έλ“œκ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ„κ²½μš° null을 λ°˜ν™˜
  • 인수둜 μ „λ‹¬ν•œ CSS μ„ νƒμžκ°€ 문법에 λ§žμ§€ μ•ŠλŠ”κ²½μš° DOMException μ—λŸ¬κ°€ λ°œμƒ

Document.prototype/Select.prototype.querySelector λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬ν•œ CSS μ„ νƒμžλ₯Ό λ§Œμ‘±μ‹œν‚€λŠ” λͺ¨λ“  μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ NodeList 객체둜 λ°˜ν™˜ν•œλ‹€. NodeList κ°μ²΄λŠ” μœ μ‚¬ λ°°μ—΄ κ°μ²΄μ΄λ©΄μ„œ μ΄ν„°λŸ¬λΈ”μ΄λ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul>
      <li class="apple">Apple</li>
      <li class="banana">Banana</li>
      <li class="orange">Orange</li>
    </ul>
    <script>
      // class μ–΄νŠΈλ¦¬λ·°νŠΈ 값이 'banana'인 첫 번째 μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€.
      const $elem = document.querySelector('.banana');

      // μ·¨λ“ν•œ μš”μ†Œ λ…Έλ“œμ˜ style.color ν”„λ‘œνΌν‹° 값을 λ³€κ²½ν•œλ‹€.
      $elem.style.color = 'red';
    </script>
  </body>
</html>
  • 인수둜 μ „λ‹¬ν•œ CSS μ„ νƒμžλ₯Ό λ§Œμ‘±μ‹œν‚€λŠ” μš”μ†Œκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 경우 빈 NodeListλ₯Ό λ°˜ν™˜
  • 인수둜 μ „λ‹¬ν•œ CSS μ„ νƒμžκ°€ 문법에 λ§žμ§€ μ•ŠλŠ”κ²½μš° DOMException μ—λŸ¬κ°€ λ°œμƒ

βœ” 39.2.5 νŠΉμ • μš”μ†Œ λ…Έλ“œλ₯Ό 취득할 수 μžˆλŠ”μ§€ 확인

Element.prototype.matches λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬ν•œ CSS μ„ νƒμžλ₯Ό 톡해 νŠΉμ • μš”μ†Œ λ…Έλ“œλ₯Ό 취득할 수 μžˆλŠ”μ§€ ν™•μΈν•œλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li class="apple">Apple</li>
      <li class="banana">Banana</li>
      <li class="orange">Orange</li>
    </ul>
  </body>
  <script>
    const $apple = document.querySelector('.apple');

    // $apple λ…Έλ“œλŠ” '#fruits > li.apple'둜 취득할 수 μžˆλ‹€.
    console.log($apple.matches('#fruits > li.apple'));  // true

    // $apple λ…Έλ“œλŠ” '#fruits > li.banana'둜 취득할 수 μ—†λ‹€.
    console.log($apple.matches('#fruits > li.banana')); // false
  </script>
</html>

βœ” 39.2.6 HTMLCollectionκ³Ό NodeList

HTMLCollectionκ³Ό NodeListλŠ” DOM APIκ°€ μ—¬λŸ¬ 개의 κ²°κ³Ό 값을 λ°˜ν™˜ν•˜κΈ° μœ„ν•œ DOM μ»¬λ ‰μ…˜ 객체둜, λͺ¨λ‘ μœ μ‚¬ λ°°μ—΄ κ°μ²΄μ΄λ©΄μ„œ μ΄ν„°λŸ¬λΈ”μ΄λ‹€.

HTMLCollectionκ³Ό NodeList의 μ€‘μš”ν•œ νŠΉμ§•μ€ λ…Έλ“œ 객체의 μƒνƒœ λ³€ν™”λ₯Ό μ‹€μ‹œκ°„μœΌλ‘œ λ°˜μ˜ν•˜λŠ” μ‚΄μ•„ μžˆλŠ”(live) κ°μ²΄λΌλŠ” 것이닀.

  • HTMLCollection getElementsByTagName, getElementsByClassName λ©”μ„œλ“œκ°€ λ°˜ν™˜ν•˜λŠ” HTMLCollection κ°μ²΄λŠ” λ…Έλ“œ 객체의 μƒνƒœ λ³€ν™”λ₯Ό μ‹€μ‹œκ°„μœΌλ‘œ λ°˜μ˜ν•˜λŠ” μ‚΄μ•„ μžˆλŠ” DOM μ»¬λ ‰μ…˜ 객체닀. λ”°λΌμ„œ HTMLCollection 객체λ₯Ό for문으둜 μˆœνšŒν•˜λ©΄μ„œ λ…Έλ“œ 객체의 μƒνƒœλ₯Ό λ³€κ²½ν•΄μ•Ό ν•  λ•Œ μ£Όμ˜ν•΄μ•Ό ν•œλ‹€.
  • NodeList HTMLCollection 객체의 λΆ€μž‘μš©μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ getElementsByTagName, getElementsByClassName λŒ€μ‹  querySelectorAll λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 방법도 μžˆλ‹€. querySelectorAll λ©”μ„œλ“œλŠ” DOM μ»¬λ ‰μ…˜ 객체인 NodeList 객체λ₯Ό λ°˜ν™˜ν•œλ‹€. μ΄λ•Œ NodeList κ°μ²΄λŠ” μ‹€μ‹œκ°„μœΌλ‘œ λ…Έλ“œμ˜ μƒνƒœ 변경을 λ°˜μ˜ν•˜μ§€ μ•ŠλŠ”(non-live) 객체닀. ν•˜μ§€λ§Œ childNodes ν”„λ‘œνΌν‹°κ°€ λ°˜ν™˜ν•˜λŠ” NodeList κ°μ²΄λŠ” HTMLCollection 객체와 같이 μ‹€μ‹œκ°„μœΌλ‘œ λ…Έλ“œ 객체의 μƒνƒœ 변경을 λ°˜μ˜ν•˜λŠ” libe 객체둜 λ™μž‘ν•˜λ―€λ‘œ μ£Όμ˜κ°€ ν•„μš”ν•˜λ‹€.

λ”°λΌμ„œ λ…Έλ“œ 객체의 μƒνƒœ λ³€κ²½κ³Ό 상관없이 μ•ˆμ „ν•˜κ²Œ DOM μ»¬λ ‰μ…˜μ„ μ‚¬μš©ν•˜λ €λ©΄ HTMLCollection μ΄λ‚˜ NodeList 객체λ₯Ό λ°°μ—΄λ‘œ λ³€ν™˜ν•˜μ—¬ μ‚¬μš©ν•˜λŠ” 것을 ꢌμž₯ν•œλ‹€.

HTMLCollectionκ³Ό NodeList κ°μ²΄λŠ” λͺ¨λ‘ μœ μ‚¬ λ°°μ—΄ κ°μ²΄μ΄λ©΄μ„œ μ΄ν„°λŸ¬λΈ”μ΄λ―€λ‘œ μŠ€ν”„λ ˆλ“œ λ¬Έλ²•μ΄λ‚˜ Array.from λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ κ°„λ‹¨νžˆ λ°°μ—΄λ‘œ λ³€ν™˜ν•  수 μžˆλ‹€.

🌺 39.3 μš”μ†Œ 탐색

Node, Element μΈν„°νŽ˜μ΄μŠ€λŠ” DOM νŠΈλ¦¬μƒμ˜ λ…Έλ“œλ₯Ό 탐색할 수 μžˆλ„λ‘ 트리 탐색 ν”„λ‘œνΌν‹°λ₯Ό μ œκ³΅ν•œλ‹€.

parentNode, previousSibling, firstChild, childNodes ν”„λ‘œνΌν‹°λŠ” Node.prototype이 μ œκ³΅ν•˜κ³ , ν”„λ‘œνΌν‹°ν‚€μ— Elementκ°€ ν¬ν•¨λœ previousElementSibling, nextElementSiblingκ³Ό children ν”„λ‘œνΌν‹°λŠ” Element.prototype이 μ œκ³΅ν•œλ‹€.

λ…Έλ“œ 탐색 ν”„λ‘œνΌν‹°λŠ” setter 없이 getter만 μ‘΄μž¬ν•˜λŠ” 읽기 μ „μš© μ ‘κ·Όμž ν”„λ‘œνΌν‹°μ΄λ‹€.

βœ” 39.3.1 곡백 ν…μŠ€νŠΈ λ…Έλ“œ

HTML μš”μ†Œ μ‚¬μ΄μ˜ 슀페이슀, νƒ­, μ€„λ°”κΏˆ(κ°œν–‰) λ“±μ˜ 곡백 λ¬ΈμžλŠ” ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό μƒμ„±ν•œλ‹€.

βœ” 39.3.2 μžμ‹ λ…Έλ“œ 탐색

  • Node.prototype.childNodes μžμ‹ λ…Έλ“œλ₯Ό λͺ¨λ‘ νƒμƒ‰ν•˜μ—¬ DOM μ»¬λ ‰μ…˜ 객체인 NodeList에 λ‹΄μ•„ λ°˜ν™˜ν•œλ‹€.Β childNodes ν”„λ‘œνΌν‹°κ°€ λ°˜ν™˜ν•œ NodeListμ—λŠ” μš”μ†Œ λ…Έλ“œλΏλ§Œ μ•„λ‹ˆλΌ ν…μŠ€νŠΈ λ…Έλ“œλ„ ν¬ν•¨λ˜μ–΄ μžˆμ„ 수 μžˆλ‹€.
  • Element.prototype.children μžμ‹ λ…Έλ“œ μ€‘μ—μ„œ μš”μ†Œ λ…Έλ“œλ§Œ λͺ¨λ‘ νƒμƒ‰ν•˜μ—¬ DOM μ»¬λ ‰μ…˜ 객체인 HTMLCollection에 λ‹΄μ•„ λ°˜ν™˜ν•œλ‹€.Β children ν”„λ‘œνΌν‹°κ°€ λ°˜ν™˜ν•œ HTMLCollectionμ—λŠ” ν…μŠ€νŠΈ λ…Έλ“œκ°€ ν¬ν•¨λ˜μ§€ μ•ŠλŠ”λ‹€.
  • Node.prototype.firstChild 첫 번째 μžμ‹ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•œλ‹€. ν…μŠ€νŠΈ λ…Έλ“œμ΄κ±°λ‚˜ μš”μ†Œ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•œλ‹€.
  • Node.prototype.lastChild λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•œλ‹€. ν…μŠ€νŠΈ λ…Έλ“œμ΄κ±°λ‚˜ μš”μ†Œ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•œλ‹€.
  • Element.prototype.firstElementChild 첫 번째 μžμ‹ μš”μ†Œ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•œλ‹€. μš”μ†Œ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•œλ‹€.
  • Element.prototype.lastElementChild λ§ˆμ§€λ§‰ μžμ‹ μš”μ†Œ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•œλ‹€. μš”μ†Œ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•œλ‹€.
<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li class="apple">Apple</li>
      <li class="banana">Banana</li>
      <li class="orange">Orange</li>
    </ul>
  </body>
  <script>
    // λ…Έλ“œ νƒμƒ‰μ˜ 기점이 λ˜λŠ” #fruits μš”μ†Œ λ…Έλ“œλ₯Ό μ·¨λ“ν•œλ‹€.
    const $fruits = document.getElementById('fruits');

    // #fruits μš”μ†Œμ˜ λͺ¨λ“  μžμ‹ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
    // childNodes ν”„λ‘œνΌν‹°κ°€ λ°˜ν™˜ν•œ NodeListμ—λŠ” μš”μ†Œ λ…Έλ“œλΏλ§Œ μ•„λ‹ˆλΌ ν…μŠ€νŠΈ λ…Έλ“œλ„ ν¬ν•¨λ˜μ–΄ μžˆλ‹€.
    console.log($fruits.childNodes);
    // NodeList(7) [text, li.apple, text, li.banana, text, li.orange, text]

    // #fruits μš”μ†Œμ˜ λͺ¨λ“  μžμ‹ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
    // children ν”„λ‘œνΌν‹°κ°€ λ°˜ν™˜ν•œ HTMLCollectionμ—λŠ” μš”μ†Œ λ…Έλ“œλ§Œ ν¬ν•¨λ˜μ–΄ μžˆλ‹€.
    console.log($fruits.children);
    // HTMLCollection(3) [li.apple, li.banana, li.orange]

    // #fruits μš”μ†Œμ˜ 첫 번째 μžμ‹ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
    // firstChild ν”„λ‘œνΌν‹°λŠ” ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•  μˆ˜λ„ μžˆλ‹€.
    console.log($fruits.firstChild); // #text

    // #fruits μš”μ†Œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
    // lastChild ν”„λ‘œνΌν‹°λŠ” ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•  μˆ˜λ„ μžˆλ‹€.
    console.log($fruits.lastChild); // #text

    // #fruits μš”μ†Œμ˜ 첫 번째 μžμ‹ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
    // firstElementChild ν”„λ‘œνΌν‹°λŠ” μš”μ†Œ λ…Έλ“œλ§Œ λ°˜ν™˜ν•œλ‹€.
    console.log($fruits.firstElementChild); // li.apple

    // #fruits μš”μ†Œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
    // lastElementChild ν”„λ‘œνΌν‹°λŠ” μš”μ†Œ λ…Έλ“œλ§Œ λ°˜ν™˜ν•œλ‹€.
    console.log($fruits.lastElementChild); // li.orange
  </script>
</html>

βœ” 39.3.3 μžμ‹ λ…Έλ“œ 쑴재 확인

Node.prototype.hasChildNodes λ©”μ„œλ“œλŠ” μžμ‹ λ…Έλ“œμ˜ 쑴재λ₯Ό λΆ€μšΈλ‘œ λ°˜ν™˜ν•œλ‹€. μ΄λ•Œ, μžμ‹ λ…Έλ“œμ—μ„œ ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό ν¬ν•¨ν•œλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
    </ul>
  </body>
  <script>
    // λ…Έλ“œ νƒμƒ‰μ˜ 기점이 λ˜λŠ” #fruits μš”μ†Œ λ…Έλ“œλ₯Ό μ·¨λ“ν•œλ‹€.
    const $fruits = document.getElementById('fruits');

    // #fruits μš”μ†Œμ— μžμ‹ λ…Έλ“œκ°€ μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•œλ‹€.
    // hasChildNodes λ©”μ„œλ“œλŠ” ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό ν¬ν•¨ν•˜μ—¬ μžμ‹ λ…Έλ“œμ˜ 쑴재λ₯Ό ν™•μΈν•œλ‹€.
    console.log($fruits.hasChildNodes()); // true
  </script>
</html>

μžμ‹ λ…Έλ“œμ€‘ ν…μŠ€νŠΈ λ…Έλ“œκ°€ μ•„λ‹Œ μš”μ†Œ λ…Έλ“œκ°€ μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•˜λ €λ©΄children.length λ˜λŠ” Element μΈν„°νŽ˜μ΄μŠ€μ˜ childElementCount ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•œλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
    </ul>
  </body>
  <script>
    // λ…Έλ“œ νƒμƒ‰μ˜ 기점이 λ˜λŠ” #fruits μš”μ†Œ λ…Έλ“œλ₯Ό μ·¨λ“ν•œλ‹€.
    const $fruits = document.getElementById('fruits');

    // hasChildNodes λ©”μ„œλ“œλŠ” ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό ν¬ν•¨ν•˜μ—¬ μžμ‹ λ…Έλ“œμ˜ 쑴재λ₯Ό ν™•μΈν•œλ‹€.
    console.log($fruits.hasChildNodes()); // true

    // μžμ‹ λ…Έλ“œ 쀑에 ν…μŠ€νŠΈ λ…Έλ“œκ°€ μ•„λ‹Œ μš”μ†Œ λ…Έλ“œκ°€ μ‘΄μž¬ν•˜λŠ”μ§€λŠ” ν™•μΈν•œλ‹€.
    console.log(!!$fruits.children.length); // 0 -> false
    // μžμ‹ λ…Έλ“œ 쀑에 ν…μŠ€νŠΈ λ…Έλ“œκ°€ μ•„λ‹Œ μš”μ†Œ λ…Έλ“œκ°€ μ‘΄μž¬ν•˜λŠ”μ§€λŠ” ν™•μΈν•œλ‹€.
    console.log(!!$fruits.childElementCount); // 0 -> false
  </script>
</html>

βœ” 39.3.4 μš”μ†Œ λ…Έλ“œμ˜ ν…μŠ€νŠΈ λ…Έλ“œ 탐색

firstChild λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ μš”μ†Œ λ…Έλ“œμ˜ ν…μŠ€νŠΈ λ…Έλ“œμ— μ ‘κ·Όν•  수 μžˆλ‹€.

<!DOCTYPE html>
<html>
<body>
  <div id="foo">Hello</div>
  <script>
    // μš”μ†Œ λ…Έλ“œμ˜ ν…μŠ€νŠΈ λ…Έλ“œλŠ” firstChild ν”„λ‘œνΌν‹°λ‘œ μ ‘κ·Όν•  수 μžˆλ‹€.
    console.log(document.getElementById('foo').firstChild); // #text
  </script>
</body>
</html>

βœ” 39.3.5 λΆ€λͺ¨ λ…Έλ“œ 탐색

Node.prototype.parentNode ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•΄λ¦¬ν”„ λ…Έλ“œμΈ λΆ€λͺ¨λ…Έλ“œλ₯Ό 탐색할 수 μžˆλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li class="apple">Apple</li>
      <li class="banana">Banana</li>
      <li class="orange">Orange</li>
    </ul>
  </body>
  <script>
    // λ…Έλ“œ νƒμƒ‰μ˜ 기점이 λ˜λŠ” .banana μš”μ†Œ λ…Έλ“œλ₯Ό μ·¨λ“ν•œλ‹€.
    const $banana = document.querySelector('.banana');

    // .banana μš”μ†Œ λ…Έλ“œμ˜ λΆ€λͺ¨ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
    console.log($banana.parentNode); // ul#fruits
  </script>
</html>

βœ” 39.3.6 ν˜•μ œ λ…Έλ“œ 탐색

λΆ€λͺ¨ λ…Έλ“œκ°€ 같은 ν˜•μ œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜λ €λ©΄ λ‹€μŒκ³Ό 같은 λ…Έλ“œ 탐색 ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•œλ‹€.

  • Node.prototype.previousSibling λΆ€λͺ¨ λ…Έλ“œκ°€ 같은 ν˜•μ œ λ…Έλ“œ μ€‘μ—μ„œ μžμ‹ μ˜ 이전 ν˜•μ œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€. previousSibling ν”„λ‘œνΌν‹°κ°€ λ°˜ν™˜ν•˜λŠ” ν˜•μ œ λ…Έλ“œλŠ” μš”μ†Œ λ…Έλ“œλΏλ§Œ μ•„λ‹ˆλΌ ν…μŠ€νŠΈ λ…Έλ“œμΌ μˆ˜λ„ μžˆλ‹€.
  • Node.prototype.nextSibling λΆ€λͺ¨ λ…Έλ“œκ°€ 같은 ν˜•μ œ λ…Έλ“œ μ€‘μ—μ„œ μžμ‹ μ˜ λ‹€μŒ ν˜•μ œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€. μš”μ†Œ λ…Έλ“œλΏλ§Œ μ•„λ‹ˆλΌ ν…μŠ€νŠΈ λ…Έλ“œμΌ μˆ˜λ„ μžˆλ‹€.
  • Element.prototype.previousElementSibling λΆ€λͺ¨ λ…Έλ“œκ°€ 같은 ν˜•μ œ λ…Έλ“œ μ€‘μ—μ„œ μžμ‹ μ˜ 이전 ν˜•μ œ μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€. μš”μ†Œ λ…Έλ“œλ§Œ λ°˜ν™˜ν•œλ‹€.
  • Element.prototype.nextElementSibling λΆ€λͺ¨ λ…Έλ“œκ°€ 같은 ν˜•μ œ λ…Έλ“œ μ€‘μ—μ„œ μžμ‹ μ˜ λ‹€μŒ ν˜•μ œ μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€. μš”μ†Œ λ…Έλ“œλ§Œ λ°˜ν™˜ν•œλ‹€.
    <!DOCTYPE html>
    <html>
      <body>
        <ul id="fruits">
          <li class="apple">Apple</li>
          <li class="banana">Banana</li>
          <li class="orange">Orange</li>
        </ul>
      </body>
      <script>
        // λ…Έλ“œ νƒμƒ‰μ˜ 기점이 λ˜λŠ” #fruits μš”μ†Œ λ…Έλ“œλ₯Ό μ·¨λ“ν•œλ‹€.
        const $fruits = document.getElementById('fruits');
    
        // #fruits μš”μ†Œμ˜ 첫 번째 μžμ‹ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
        // firstChild ν”„λ‘œνΌν‹°λŠ” μš”μ†Œ λ…Έλ“œλΏλ§Œ μ•„λ‹ˆλΌ ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•  μˆ˜λ„ μžˆλ‹€.
        const { firstChild } = $fruits;
        console.log(firstChild); // #text
    
        // #fruits μš”μ†Œμ˜ 첫 번째 μžμ‹ λ…Έλ“œ(ν…μŠ€νŠΈ λ…Έλ“œ)의 λ‹€μŒ ν˜•μ œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
        // nextSibling ν”„λ‘œνΌν‹°λŠ” μš”μ†Œ λ…Έλ“œλΏλ§Œ μ•„λ‹ˆλΌ ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•  μˆ˜λ„ μžˆλ‹€.
        const { nextSibling } = firstChild;
        console.log(nextSibling); // li.apple
    
        // li.apple μš”μ†Œμ˜ 이전 ν˜•μ œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
        // previousSibling ν”„λ‘œνΌν‹°λŠ” μš”μ†Œ λ…Έλ“œλΏλ§Œ μ•„λ‹ˆλΌ ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•  μˆ˜λ„ μžˆλ‹€.
        const { previousSibling } = nextSibling;
        console.log(previousSibling); // #text
    
        // #fruits μš”μ†Œμ˜ 첫 번째 μžμ‹ μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
        // firstElementChild ν”„λ‘œνΌν‹°λŠ” μš”μ†Œ λ…Έλ“œλ§Œ λ°˜ν™˜ν•œλ‹€.
        const { firstElementChild } = $fruits;
        console.log(firstElementChild); // li.apple
    
        // #fruits μš”μ†Œμ˜ 첫 번째 μžμ‹ μš”μ†Œ λ…Έλ“œ(li.apple)의 λ‹€μŒ ν˜•μ œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€.
        // nextElementSibling ν”„λ‘œνΌν‹°λŠ” μš”μ†Œ λ…Έλ“œλ§Œ λ°˜ν™˜ν•œλ‹€.
        const { nextElementSibling } = firstElementChild;
        console.log(nextElementSibling); // li.banana
    
        // li.banana μš”μ†Œμ˜ 이전 ν˜•μ œ μš”μ†Œ λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€
        // previousElementSibling ν”„λ‘œνΌν‹°λŠ” μš”μ†Œ λ…Έλ“œλ§Œ λ°˜ν™˜ν•œλ‹€.
        const { previousElementSibling } = nextElementSibling;
        console.log(previousElementSibling); // li.apple
      </script>
    </html>

🌺 39.4 λ…Έλ“œ 정보 취득

  • Node.prototype.nodeType : λ…Έλ“œ 객체의 μ’…λ₯˜, 즉 λ…Έλ“œ νƒ€μž…μ„ λ‚˜νƒ€λ‚΄λŠ” μƒμˆ˜λ₯Ό λ°˜ν™˜ν•œλ‹€. λ…Έλ“œ νƒ€μž… μƒμˆ˜λŠ” Node에 μ •μ˜λ˜μ–΄ μžˆλ‹€. Node.ELEMENT_NODE: μš”μ†Œ λ…Έλ“œ νƒ€μž…μ„ λ‚˜νƒ€λ‚΄λŠ” μƒμˆ˜ 1을 λ°˜ν™˜ Node.TEXT_NODE: ν…μŠ€νŠΈ λ…Έλ“œ νƒ€μž…μ„ λ‚˜νƒ€λ‚΄λŠ” μƒμˆ˜ 3을 λ°˜ν™˜ Node.DOCUMENT_NODE: λ¬Έμ„œ λ…Έλ“œ νƒ€μž…μ„ λ‚˜νƒ€λ‚΄λŠ” μƒμˆ˜ 9λ₯Ό λ°˜ν™˜
  • Node.prototype.nodeName : λ…Έλ“œμ˜ 이름을 λ¬Έμžμ—΄λ‘œ λ°˜ν™˜ν•œλ‹€. μš”μ†Œ λ…Έλ“œ: λŒ€λ¬Έμž λ¬Έμžμ—΄λ‘œ νƒœκ·Έ 이름("UL", "LI"λ“±)을 λ°˜ν™˜ ν…μŠ€νŠΈ λ…Έλ“œ: λ¬Έμžμ—΄ "#text"λ₯Ό λ°˜ν™˜ λ¬Έμ„œ λ…Έλ“œ: λ¬Έμžμ—΄ "#document"λ₯Ό λ°˜ν™˜
<!DOCTYPE html>
<html>
  <body>
    <div id="foo">Hello</div>
  </body>
  <script>
    // λ¬Έμ„œ λ…Έλ“œμ˜ λ…Έλ“œ 정보λ₯Ό μ·¨λ“ν•œλ‹€.
    console.log(document.nodeType); // 9
    console.log(document.nodeName); // #document

    // μš”μ†Œ λ…Έλ“œμ˜ λ…Έλ“œ 정보λ₯Ό μ·¨λ“ν•œλ‹€.
    const $foo = document.getElementById('foo');
    console.log($foo.nodeType); // 1
    console.log($foo.nodeName); // DIV

    // ν…μŠ€νŠΈ λ…Έλ“œμ˜ λ…Έλ“œ 정보λ₯Ό μ·¨λ“ν•œλ‹€.
    const $textNode = $foo.firstChild;
    console.log($textNode.nodeType); // 3
    console.log($textNode.nodeName); // #text
</script>
</html>

🌺 39.5 μš”μ†Œ λ…Έλ“œμ˜ ν…μŠ€νŠΈ μ‘°μž‘

βœ” 39.5.1 nodeValue

λ…Έλ“œ 탐색, λ…Έλ“œ 정보 ν”„λ‘œνΌν‹°λŠ” λͺ¨λ‘ 읽기 μ „μš© μ ‘κ·Όμž ν”„λ‘œνΌν‹°μ΄μ§€λ§Œ, Node.prototype.nodeValue ν”„λ‘œνΌν‹°λŠ” setter와 getter λͺ¨λ‘ μ‘΄μž¬ν•˜λŠ” μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ‘œ 참쑰와 할당이 λͺ¨λ‘ κ°€λŠ₯ν•˜λ‹€.

λ…Έλ“œ 객체의 nodeValue ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•˜λ©΄ λ…Έλ“œ 객체의 값을 λ°˜ν™˜ν•œλ‹€. 이 λ•Œ λ…Έλ“œ 객체의 값은 ν…μŠ€νŠΈ λ…Έλ“œμ˜ ν…μŠ€νŠΈμ΄λ©° λ¬Έμ„œ λ…Έλ“œλ‚˜ μš”μ†Œ λ…Έλ“œμΌ 경우 null을 λ°˜ν™˜ν•œλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <div id="foo">Hello</div>
  </body>
  <script>
    // λ¬Έμ„œ λ…Έλ“œμ˜ nodeValue ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•œλ‹€.
    console.log(document.nodeValue); // null

    // μš”μ†Œ λ…Έλ“œμ˜ nodeValue ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•œλ‹€.
    const $foo = document.getElementById('foo');
    console.log($foo.nodeValue); // null

    // ν…μŠ€νŠΈ λ…Έλ“œμ˜ nodeValue ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•œλ‹€.
    const $textNode = $foo.firstChild;
    console.log($textNode.nodeValue); // Hello
  </script>
</html>

ν…μŠ€νŠΈ λ…Έλ“œμ˜ nodeValue ν”„λ‘œνΌν‹°μ— 값을 ν• λ‹Ήν•˜λ©΄ ν…μŠ€νŠΈ λ…Έλ“œμ˜ 값을 λ³€κ²½ν•  수 μžˆλ‹€. λ”°λΌμ„œ μš”μ†Œ λ…Έλ“œμ˜ ν…μŠ€νŠΈλ₯Ό λ³€κ²½ν•˜λ €λ©΄ λ‹€μŒκ³Ό 같은 μˆœμ„œμ˜ μ²˜λ¦¬κ°€ ν•„μš”ν•˜λ‹€.

  • ν…μŠ€νŠΈλ₯Ό λ³€κ²½ν•  μš”μ†Œ λ…Έλ“œ 취득
  • ν…μŠ€νŠΈ λ…Έλ“œλŠ” μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμ΄λ―€λ‘œ firstChild ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•˜μ—¬ μ·¨λ“ν•œ μš”μ†Œ λ…Έλ“œμ˜ ν…μŠ€νŠΈ λ…Έλ“œ 탐색
  • νƒμƒ‰ν•œ ν…μŠ€νŠΈ λ…Έλ“œμ˜ nodeValue ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•˜μ—¬ ν…μŠ€νŠΈ λ…Έλ“œμ˜ 값을 λ³€κ²½
<!DOCTYPE html>
<html>
  <body>
    <div id="foo">Hello</div>
  </body>
  <script>
    // 1. #foo μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμΈ ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό μ·¨λ“ν•œλ‹€.
    const $textNode = document.getElementById('foo').firstChild;

    // 2. nodeValue ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•˜μ—¬ ν…μŠ€νŠΈ λ…Έλ“œμ˜ 값을 λ³€κ²½ν•œλ‹€.
    $textNode.nodeValue = 'World';

    console.log($textNode.nodeValue); // World
  </script>
</html>

βœ” 39.5.2 textContent

**Node.prototype.textContent ν”„λ‘œνΌν‹°λŠ”** setter와 getter λͺ¨λ‘ μ‘΄μž¬ν•˜λŠ” μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ‘œ μš”μ†Œ λ…Έλ“œμ˜ ν…μŠ€νŠΈμ™€ λͺ¨λ“  μžμ† λ…Έλ“œμ˜ ν…μŠ€νŠΈλ₯Ό λͺ¨λ‘ μ·¨λ“ν•˜κ±°λ‚˜ λ³€κ²½ν•œλ‹€.

μš”μ†Œ λ…Έλ“œμ˜ textContent ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•˜λ©΄ μš”μ†Œ λ…Έλ“œμ˜ μ½˜ν…μΈ  μ˜μ—­(μ‹œμž‘ νƒœκ·Έμ™€ μ’…λ£Œ νƒœκ·Έ 사이) λ‚΄μ˜ ν…μŠ€νŠΈλ₯Ό λͺ¨λ‘ λ°˜ν™˜ν•œλ‹€. λ‹€μ‹œ 말해, μš”μ†Œ λ…Έλ“œμ˜ childNodes ν”„λ‘œνΌν‹°κ°€ λ°˜ν™˜ν•œ λͺ¨λ“  λ…Έλ“œλ“€μ˜ ν…μŠ€νŠΈ λ…Έλ“œμ˜ κ°’, 즉 ν…μŠ€νŠΈλ₯Ό λͺ¨λ‘ λ°˜ν™˜ν•œλ‹€.

<!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>

참고둜 textContent ν”„λ‘œνΌν‹°μ™€ μœ μ‚¬ν•œ λ™μž‘μ„ ν•˜λŠ” innerTextλŠ” λ‹€μŒκ³Ό 같은 이유둜 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”κ²ƒμ΄ μ’‹λ‹€.

  • innerText ν”„λ‘œνΌν‹°λŠ” CSS에 μˆœμ’…μ μ΄λ‹€. 예λ₯Ό λ“€μ–΄, innerText ν”„λ‘œνΌν‹°λŠ” CSS에 μ˜ν•΄ λΉ„ν‘œμ‹œλ‘œ μ§€μ •λœ μš”μ†Œ λ…Έλ“œμ˜ ν…μŠ€νŠΈλ₯Ό λ°˜ν™˜ν•˜μ§€ μ•ŠλŠ”λ‹€. (visibility : hidden;)
  • innerText ν”„λ‘œνΌν‹°λŠ” CSSλ₯Ό κ³ λ €ν•΄μ•Ό ν•˜λ―€λ‘œ textContent ν”„λ‘œνΌν‹°λ³΄λ‹€ λŠλ¦¬λ‹€.

🌺 39.6 DOM μ‘°μž‘

DOM μ‘°μž‘μ€ μƒˆλ‘œμš΄ λ…Έλ“œλ₯Ό μƒμ„±ν•˜μ—¬ DOM에 μΆ”κ°€ν•˜κ±°λ‚˜ κΈ°μ‘΄ λ…Έλ“œλ₯Ό μ‚­μ œ λ˜λŠ” κ΅μ²΄ν•˜λŠ” 것을 λ§ν•œλ‹€. DOM μ‘°μž‘μ— μ˜ν•΄ DOM에 μƒˆλ‘œμš΄ λ…Έλ“œκ°€ μΆ”κ°€λ˜κ±°λ‚˜ μ‚­μ œλ˜λ©΄ λ¦¬ν”Œλ‘œμš°μ™€ λ¦¬νŽ˜μΈνŠΈκ°€ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ— μ„±λŠ₯을 μœ„ν•΄ μ£Όμ˜ν•΄μ•Ό ν•œλ‹€.

βœ” 39.6.1 innerHTML

**Element.prototype.innerHTML ν”„λ‘œνΌν‹°λŠ” setter와 getter λͺ¨λ‘ μ‘΄μž¬ν•˜λŠ” μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ‘œ μš”μ†Œ λ…Έλ“œμ˜ HTML λ§ˆν¬μ—…μ„ μ·¨λ“ν•˜κ±°λ‚˜ λ³€κ²½**ν•œλ‹€.

μš”μ†Œ λ…Έλ“œμ˜ innerHTML ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•˜λ©΄ μš”μ†Œ λ…Έλ“œμ˜ μ½˜ν…μΈ  μ˜μ—­(μ‹œμž‘ νƒœκ·Έμ™€ μ’…λ£Œ νƒœκ·Έ 사이) 에 ν¬ν•¨λœ λͺ¨λ“  HTML λ§ˆν¬μ—…μ„ λ¬Έμžμ—΄λ‘œ λ°˜ν™˜ν•œλ‹€.

λ‚΄μ˜ ν…μŠ€νŠΈλ₯Ό λͺ¨λ‘ λ°˜ν™˜ν•œλ‹€. λ‹€μ‹œ 말해, μš”μ†Œ λ…Έλ“œμ˜ childNodes ν”„λ‘œνΌν‹°κ°€ λ°˜ν™˜ν•œ λͺ¨λ“  λ…Έλ“œλ“€μ˜ ν…μŠ€νŠΈ λ…Έλ“œμ˜ κ°’, 즉 ν…μŠ€νŠΈλ₯Ό λͺ¨λ‘ λ°˜ν™˜ν•œλ‹€

<!DOCTYPE html>
<html>
  <body>
    <div id="foo">Hello <span>world!</span></div>
  </body>
  <script>
    // #foo μš”μ†Œμ˜ μ½˜ν…μΈ  μ˜μ—­ λ‚΄μ˜ HTML λ§ˆν¬μ—…μ„ λ¬Έμžμ—΄λ‘œ μ·¨λ“ν•œλ‹€.
    console.log(document.getElementById('foo').innerHTML);

    // "Hello <span>world!</span>"
  </script>
</html>

μ•žμ„œ μ‚΄νŽ΄λ³Έ textContent ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•˜λ©΄ HTML λ§ˆν¬μ—…μ„ λ¬΄μ‹œν•˜κ³  ν…μŠ€νŠΈλ§Œ λ°˜ν™˜ν•˜μ§€λ§Œ, innerHTML을 μ‚¬μš©ν•˜λ©΄ ν”„λ‘œνΌν‹°λŠ” HTML λ§ˆν¬μ—…μ΄ ν¬ν•¨λœ λ¬Έμžμ—΄μ„ κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•œλ‹€. 이처럼 innerHTML을 μ‚¬μš©ν•œ DOM μ‘°μž‘μ€ κ΅¬ν˜„μ΄ κ°„νŽΈν•˜κ³  μ§κ΄€μ μ΄μ§€λ§Œ 크둜슀 μ‚¬μ΄νŠΈ μŠ€ν¬λ¦½νŒ… 곡격에 μ·¨μ•½ν•˜λ©°, μ‚½μž… μœ„μΉ˜ λ˜ν•œ 지정할 수 μ—†μ–΄ λΉ„νš¨μœ¨μ μ΄λ‹€.

βœ” 39.6.2 insertAdjacentHTML λ©”μ„œλ“œ

**Element.prototype.inserdAdjacentHTML(position, DOMString) λ©”μ„œλ“œλŠ” κΈ°μ‘΄ μš”μ†Œλ₯Ό μ œκ±°ν•˜μ§€ μ•ŠμœΌλ©΄μ„œ μœ„μΉ˜λ₯Ό 지정해 μƒˆλ‘œμš΄ μš”μ†Œλ₯Ό μ‚½μž…**ν•œλ‹€.

insertAdjacentHTML λ©”μ„œλ“œλŠ” 두 번째 인수둜 μ „λ‹¬ν•œ HTML λ§ˆν¬μ—… λ¬Έμžμ—΄(DOMString)을 νŒŒμ‹±ν•˜κ³  κ·Έ 결과둜 μƒμ„±λœ λ…Έλ“œλ₯Ό 첫 번째 인수둜 μ „λ‹¬ν•œ μœ„μΉ˜(position)에 μ‚½μž…ν•˜μ—¬ DOM에 λ°˜μ˜ν•œλ‹€. 첫 번째 인수둜 전달할 수 μžˆλŠ” λ¬Έμžμ—΄μ€ β€˜beforebegin’, β€˜afterbegin’, β€˜beforeend’, β€˜afterbegin’ 의 4가지닀.

<!DOCTYPE html>
<html>
  <body>
    <!-- beforebegin -->
    <div id="foo">
      <!-- afterbegin -->
      text
      <!-- beforeend -->
    </div>
    <!-- afterend -->
  </body>
  <script>
    const $foo = document.getElementById('foo');

    $foo.insertAdjacentHTML('beforebegin', '<p>beforebegin</p>');
    $foo.insertAdjacentHTML('afterbegin', '<p>afterbegin</p>');
    $foo.insertAdjacentHTML('beforeend', '<p>beforeend</p>');
    $foo.insertAdjacentHTML('afterend', '<p>afterend</p>');
  </script>
</html>

innerHTML ν”„λ‘œνΌν‹°λ³΄λ‹€ 효율적이고 λΉ λ₯΄λ‚˜, HTML λ§ˆν¬μ—…λ¬Έμžμ—΄μ„ νŒŒμ‹±ν•˜λ―€λ‘œ 크둜슀 μ‚¬μ΄νŠΈ μŠ€ν¬λ¦½νŒ… 곡격에 μ·¨μ•½ν•˜λ‹€λŠ”μ μ€ λ™μΌν•˜λ‹€.

βœ” 39.6.3 λ…Έλ“œ 생성과 μΆ”κ°€

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li>Apple</li>
    </ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');

    // 1. μš”μ†Œ λ…Έλ“œ 생성
    const $li = document.createElement('li');

    // 2. ν…μŠ€νŠΈ λ…Έλ“œ 생성
    const textNode = document.createTextNode('Banana');

    // 3. ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό $li μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
    $li.appendChild(textNode);

    // 4. $li μš”μ†Œ λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
    $fruits.appendChild($li);
  </script>
</html>
  • μš”μ†Œ λ…Έλ“œ 생성 Document.prototype.createElement(tagName) λ©”μ„œλ“œλŠ” μš”μ†Œ λ…Έλ“œλ₯Ό μƒμ„±ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€. createElement λ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜ tagNameμ—λŠ” νƒœκ·Έ 이름을 λ‚˜νƒ€λ‚΄λŠ” λ¬Έμžμ—΄μ„ 인수둜 전달 ν•œλ‹€. μ΄λ•Œ createElement λ©”μ„œλ“œλ‘œ μƒμ„±ν•œ μš”μ†Œ λ…Έλ“œλŠ” DOM에 μΆ”κ°€λ˜μ§€ μ•Šκ³  ν™€λ‘œ μ‘΄μž¬ν•˜λŠ” μƒνƒœμ΄λ―€λ‘œ λ³„λ„λ‘œ DOM에 μΆ”κ°€ν•΄ μ€˜μ•Ό ν•œλ‹€.
  • ν…μŠ€νŠΈ λ…Έλ“œ 생성 Document.prototype.createTextNode(text) λ©”μ„œλ“œλŠ” ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό μƒμ„±ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€. createTextNode λ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜ textμ—λŠ” ν…μŠ€νŠΈ λ…Έλ“œμ˜ κ°’μœΌλ‘œ μ‚¬μš©ν•  λ¬Έμžμ—΄μ„ 인수둜 전달 ν•œλ‹€. createTextNode λ©”μ„œλ“œκ°€ μƒμ„±ν•œ ν…μŠ€νŠΈ λ…Έλ“œ λ˜ν•œ μš”μ†Œλ…Έλ“œμ— μΆ”κ°€ν•˜λŠ” λ³„λ„μ˜ μ²˜λ¦¬κ°€ ν•„μš”ν•˜λ‹€.
  • ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€ **Node.prototype.appendChild(childNode) λ©”μ„œλ“œλŠ” λ§€κ°œλ³€μˆ˜ childNodeμ—κ²Œ 인수둜 μ „λ‹¬ν•œ λ…Έλ“œλ₯Ό appendChild λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€**ν•œλ‹€. appendChild λ©”μ„œλ“œμ˜ 인수둜 createTextNode λ©”μ„œλ“œλ‘œ μƒμ„±ν•œ ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό μ „λ‹¬ν•˜λ©΄ appendChild λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰μžμ‹ λ…Έλ“œλ‘œ ν…μŠ€νŠΈ λ…Έλ“œκ°€ μΆ”κ°€λœλ‹€. 이 과정을 톡해 Document.prototype.createElement(tagName)둜 μƒμ„±ν•œ μš”μ†Œλ…Έλ“œμ™€ Document.prototype.createTextNode(text) 둜 μƒμ„±ν•œ ν…μŠ€νŠΈ λ…Έλ“œλŠ” λΆ€μž κ΄€κ³„λ‘œ μ—°κ²°λ˜μ—ˆμ§€λ§Œ DOM에 μΆ”κ°€λ˜μ§€λŠ” μ•Šμ€ μƒνƒœμ΄λ‹€.
  • μš”μ†Œ λ…Έλ“œλ₯Ό DOM에 μΆ”κ°€ Node.prototype.appendChild λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ ν…μŠ€νŠΈ λ…Έλ“œμ™€ λΆ€μž κ΄€κ³„λ‘œ μ—°κ²°ν•œ μš”μ†Œ λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ μš”μ†Œλ‘œ μΆ”κ°€ν•œλ‹€. 이 λ•Œ λ¦¬ν”Œλ‘œμš°μ™€ λ¦¬νŽ˜μΈνŠΈκ°€ μ‹€ν–‰λœλ‹€.

βœ” 39.6.4 볡수의 λ…Έλ“œ 생성과 μΆ”κ°€

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits"></ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');

    ['Apple', 'Banana', 'Orange'].forEach(text => {
      // 1. μš”μ†Œ λ…Έλ“œ 생성
      const $li = document.createElement('li');

      // 2. ν…μŠ€νŠΈ λ…Έλ“œ 생성
      const textNode = document.createTextNode(text);

      // 3. ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό $li μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
      $li.appendChild(textNode);

      // 4. $li μš”μ†Œ λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
      $fruits.appendChild($li);
    });
  </script>
</html>

μœ„μ™€ 같이 μ—¬λŸ¬ 개의 μš”μ†Œ λ…Έλ“œλ₯Ό μƒμ„±ν•˜μ—¬ DOM에 μΆ”κ°€ν•  수 μžˆμœΌλ‚˜ μœ„μ˜ μ˜ˆμ œλŠ” λ¦¬ν”Œλ‘œμš°/λ¦¬νŽ˜μΈνŒ… λ˜ν•œ 3번 λ³€κ²½λ˜κΈ° λ•Œλ¬Έμ— 높은 λΉ„μš©μ΄ λ“€κ³  μ„±λŠ₯에 μ’‹μ§€μ•Šλ‹€.

λ”°λΌμ„œ DocumentFragment λ…Έλ“œλ₯Ό 톡해 ν•΄κ²°ν•  수 μžˆλ‹€. DocumentFragment λ…Έλ“œλŠ” λ¬Έμ„œ, μš”μ†Œ, μ–΄νŠΈλ¦¬λ·°νŠΈ, ν…μŠ€νŠΈ λ…Έλ“œμ™€ 같은 λ…Έλ“œ 객체의 μΌμ’…μœΌλ‘œ, λΆ€λͺ¨ λ…Έλ“œκ°€ μ—†μ–΄μ„œ κΈ°μ‘΄ DOMκ³ΌλŠ” λ³„λ„λ‘œ μ‘΄μž¬ν•œλ‹€λŠ” νŠΉμ§•μ΄ μžˆλ‹€. DocumentFragment λ…Έλ“œλŠ” μžμ‹ λ…Έλ“œλ“€μ˜ λΆ€λͺ¨ λ…Έλ“œλ‘œμ„œ λ³„λ„μ˜ μ„œλΈŒ DOM을 κ΅¬μ„±ν•˜μ—¬ κΈ°μ‘΄ DOM 에 μΆ”κ°€ν•˜κΈ° μœ„ν•œ μš©λ„λ‘œ μ‚¬μš©ν•œλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits"></ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');

    // DocumentFragment λ…Έλ“œ 생성
    const $fragment = document.createDocumentFragment();

    ['Apple', 'Banana', 'Orange'].forEach(text => {
      // 1. μš”μ†Œ λ…Έλ“œ 생성
      const $li = document.createElement('li');

      // 2. ν…μŠ€νŠΈ λ…Έλ“œ 생성
      const textNode = document.createTextNode(text);

      // 3. ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό $li μš”μ†Œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
      $li.appendChild(textNode);

      // 4. $li μš”μ†Œ λ…Έλ“œλ₯Ό DocumentFragment λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
      $fragment.appendChild($li);
    });

    // 5. DocumentFragment λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
    $fruits.appendChild($fragment);
  </script>
</html>

DocumentFragment λ…Έλ“œλŠ” κΈ°μ‘΄ DOMκ³ΌλŠ” λ³„λ„λ‘œ μ‘΄μž¬ν•˜λ―€λ‘œ DocumentFragment λ…Έλ“œμ— μžμ‹ λ…Έλ“œλ₯Ό μΆ”κ°€ ν•˜μ—¬λ„ κΈ°μ‘΄ DOMμ—λŠ” μ–΄λ– ν•œ 변경도 λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. λ˜ν•œ DocumentFragment λ…Έλ“œλ₯Ό DOM에 μΆ”κ°€ν•˜λ©΄ μžμ‹ μ€ 제거되고 μžμ‹ μ˜ μžμ‹ λ…Έλ“œλ§Œ DOM에 μΆ”κ°€λœλ‹€.

이 λ•Œ μ‹€μ œλ‘œ DOM 변경이 λ°œμƒν•˜λŠ” 것은 ν•œ 번 뿐이며 λ¦¬ν”Œλ‘œμš°μ™€ λ¦¬νŽ˜μΈνŠΈλ„ ν•œ 번만 μ‹€ν–‰λœλ‹€. λ”°λΌμ„œ μ—¬λŸ¬ 개의 μš”μ†Œ λ…Έλ“œλ₯Ό DOM에 μΆ”κ°€ν•˜λŠ” 경우 DocumentFragment λ…Έλ“œλ₯Ό μ‚¬μš©ν•˜λŠ”κ²ƒμ΄ 더 νš¨μœ¨μ μ΄λ‹€.

βœ” 39.6.5 λ…Έλ“œ μ‚½μž…

  • λ§ˆμ§€λ§‰ λ…Έλ“œλ‘œ μΆ”κ°€ **Node.prototype.appendChildλ©”μ„œλ“œλŠ” 인수둜 전달받은 λ…Έλ“œλ₯Ό μžμ‹ μ„ ν˜ΈμΆœν•œ λͺ¨λ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ DOM에 μΆ”κ°€**ν•œλ‹€. μ΄λ•Œ λ…Έλ“œλ₯Ό μΆ”κ°€ν•  μœ„μΉ˜λ₯Ό 지정할 수 μ—†κ³  μ–Έμ œλ‚˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€ν•œλ‹€.
    <!DOCTYPE html>
    <html>
      <body>
        <ul id="fruits">
          <li>Apple</li>
          <li>Banana</li>
        </ul>
      </body>
      <script>
        // μš”μ†Œ λ…Έλ“œ 생성
        const $li = document.createElement('li');
    
        // ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό $li μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
        $li.appendChild(document.createTextNode('Orange'));
    
        // $li μš”μ†Œ λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
        document.getElementById('fruits').appendChild($li);
      </script>
    </html>
  • μ§€μ •ν•œ μœ„μΉ˜μ— λ…Έλ“œ μ‚½μž… Node.prototype.insertBefore(newNode, childNode) λ©”μ„œλ“œλŠ” 첫 번째 인수둜 전달받은 λ…Έλ“œλ₯Ό 두 번째 인수둜 전달받은 λ…Έλ“œ μ•žμ— μ‚½μž…ν•œλ‹€.
    <!DOCTYPE html>
    <html>
      <body>
        <ul id="fruits">
          <li>Apple</li>
          <li>Banana</li>
        </ul>
      </body>
      <script>
        const $fruits = document.getElementById('fruits');
    
        // μš”μ†Œ λ…Έλ“œ 생성
        const $li = document.createElement('li');
    
        // ν…μŠ€νŠΈ λ…Έλ“œλ₯Ό $li μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œλ‘œ μΆ”κ°€
        $li.appendChild(document.createTextNode('Orange'));
    
        // $li μš”μ†Œ λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μžμ‹ μš”μ†Œ μ•žμ— μ‚½μž…
        $fruits.insertBefore($li, $fruits.lastElementChild);
        // Apple - Orange - Banana
      </script>
    </html>
    두 번째 인수둜 전달받은 λ…Έλ“œλŠ” λ°˜λ“œμ‹œ insertBefore λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμ΄μ–΄μ•Ό ν•œλ‹€. 그렇지 μ•ŠμœΌλ©΄ DOMException μ—λŸ¬κ°€ λ°œμƒν•œλ‹€. 두 번째 인수둜 전달받은 λ…Έλ“œκ°€ null이면 appendChild λ©”μ„œλ“œμ²˜λŸΌ λ™μž‘ν•œλ‹€.

βœ” 39.6.6 λ…Έλ“œ 이동

DOM에 이미 μ‘΄μž¬ν•˜λŠ” λ…Έλ“œλ₯Ό appendChild λ˜λŠ” insertBefore λ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜μ—¬ DOM에 λ‹€μ‹œ μΆ”κ°€ν•˜λ©΄ ν˜„μž¬ μœ„μΉ˜μ—μ„œ λ…Έλ“œλ₯Ό μ œκ±°ν•˜κ³  μƒˆλ‘œμš΄ μœ„μΉ˜μ— λ…Έλ“œλ₯Ό μΆ”κ°€ν•œλ‹€. 즉, λ…Έλ“œκ°€ μ΄λ™ν•œλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li>Apple</li>
      <li>Banana</li>
      <li>Orange</li>
    </ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');

    // 이미 μ‘΄μž¬ν•˜λŠ” μš”μ†Œ λ…Έλ“œλ₯Ό 취득
    const [$apple, $banana, ] = $fruits.children;

    // 이미 μ‘΄μž¬ν•˜λŠ” $apple μš”μ†Œ λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ λ…Έλ“œλ‘œ 이동
    $fruits.appendChild($apple); // Banana - Orange - Apple

    // 이미 μ‘΄μž¬ν•˜λŠ” $banana μš”μ†Œ λ…Έλ“œλ₯Ό #fruits μš”μ†Œμ˜ λ§ˆμ§€λ§‰ μžμ‹ λ…Έλ“œ μ•žμœΌλ‘œ 이동
    $fruits.insertBefore($banana, $fruits.lastElementChild);
    // Orange - Banana - Apple
  </script>
</html>

βœ” 39.6.7 λ…Έλ“œ 볡사

**Node.prototype.cloneNode([deep: true | false])** λ©”μ„œλ“œλŠ” λ…Έλ“œμ˜ 사본을 μƒμ„±ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€. λ§€κ°œλ³€μˆ˜ deep에 trueλ₯Ό 인수둜 μ „λ‹¬ν•˜λ©΄ λ…Έλ“œλ₯Ό κΉŠμ€ λ³΅μ‚¬ν•˜μ—¬ λͺ¨λ“  μžμ† λ…Έλ“œκ°€ ν¬ν•¨λœ 사본을 μƒμ„±ν•˜κ³ , falseλ₯Ό 인수둜 μ „λ‹¬ν•˜κ±°λ‚˜ μƒλž΅ν•˜λ©΄ λ…Έλ“œλ₯Ό 얕은 볡사 ν•˜μ—¬ λ…Έλ“œ μžμ‹ λ§Œμ˜ 사본을 μƒμ„±ν•œλ‹€. 얕은 λ³΅μ‚¬λ‘œ μƒμ„±λœ μš”μ†Œ λ…Έλ“œλŠ” μžμ† λ…Έλ“œλ₯Ό λ³΅μ‚¬ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ ν…μŠ€νŠΈ λ…Έλ“œλ„ μ—†λ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li>Apple</li>
    </ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');
    const $apple = $fruits.firstElementChild;

    // $apple μš”μ†Œλ₯Ό 얕은 λ³΅μ‚¬ν•˜μ—¬ 사본을 생성. ν…μŠ€νŠΈ λ…Έλ“œκ°€ μ—†λŠ” 사본이 μƒμ„±λœλ‹€.
    const $shallowClone = $apple.cloneNode();
    // 사본 μš”μ†Œ λ…Έλ“œμ— ν…μŠ€νŠΈ μΆ”κ°€
    $shallowClone.textContent = 'Banana';
    // 사본 μš”μ†Œ λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ λ…Έλ“œλ‘œ μΆ”κ°€
    $fruits.appendChild($shallowClone);

    // #fruits μš”μ†Œλ₯Ό κΉŠμ€ λ³΅μ‚¬ν•˜μ—¬ λͺ¨λ“  μžμ† λ…Έλ“œκ°€ ν¬ν•¨λœ 사본을 생성
    const $deepClone = $fruits.cloneNode(true);
    // 사본 μš”μ†Œ λ…Έλ“œλ₯Ό #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ λ…Έλ“œλ‘œ μΆ”κ°€
    $fruits.appendChild($deepClone);
  </script>
</html>

βœ” 39.6.8 λ…Έλ“œ ꡐ체

**Node.prototype.replaceChild(newChild, oldChild)** λ©”μ„œλ“œλŠ” μžμ‹ μ„ ν˜ΈμΆœν•œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œλ₯Ό λ‹€λ₯Έ λ…Έλ“œλ‘œ κ΅μ²΄ν•œλ‹€. 첫 번째 λ§€κ°œλ³€μˆ˜ newChildμ—λŠ” ꡐ체할 μƒˆλ‘œμš΄ λ…Έλ“œλ₯Ό 인수둜 μ „λ‹¬ν•˜κ³ , 두 번째 λ§€κ°œλ³€μˆ˜ oldChildμ—λŠ” 이미 μ‘΄μž¬ν•˜λŠ” ꡐ체될 λ…Έλ“œλ₯Ό 인수둜 μ „λ‹¬ν•œλ‹€. oldChild λ§€κ°œλ³€μˆ˜μ— 인수둜 μ „λ‹¬ν•œ λ…Έλ“œλŠ” replaceChild λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμ΄μ–΄μ•Ό ν•œλ‹€.

즉, replaceChild λ©”μ„œλ“œλŠ” μžμ‹ μ„ ν˜ΈμΆœν•œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμΈ oldChild λ…Έλ“œλ₯Ό newChild λ…Έλ“œλ‘œ κ΅μ²΄ν•œλ‹€. μ΄λ•Œ oldChild λ…Έλ“œλŠ” DOMμ—μ„œ μ œκ±°λœλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li>Apple</li>
    </ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');

    // κΈ°μ‘΄ λ…Έλ“œμ™€ ꡐ체할 μš”μ†Œ λ…Έλ“œλ₯Ό 생성
    const $newChild = document.createElement('li');
    $newChild.textContent = 'Banana';

    // #fruits μš”μ†Œ λ…Έλ“œμ˜ 첫 번째 μžμ‹ μš”μ†Œ λ…Έλ“œλ₯Ό $newChild μš”μ†Œ λ…Έλ“œλ‘œ ꡐ체
    $fruits.replaceChild($newChild, $fruits.firstElementChild);
  </script>
</html>

βœ” 39.6.7 λ…Έλ“œ μ‚­μ œ

**Node.prototype.removeChild(child)** λ©”μ„œλ“œλŠ” child λ§€κ°œλ³€μˆ˜μ— 인수둜 μ „λ‹¬ν•œ λ…Έλ“œλ₯Ό DOMμ—μ„œ μ‚­μ œν•œλ‹€. 인수둜 μ „λ‹¬ν•œ λ…Έλ“œλŠ” removeChild λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œμ΄μ–΄μ•Ό ν•œλ‹€.

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li>Apple</li>
      <li>Banana</li>
    </ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');

    // #fruits μš”μ†Œ λ…Έλ“œμ˜ λ§ˆμ§€λ§‰ μš”μ†Œλ₯Ό DOMμ—μ„œ μ‚­μ œ
    $fruits.removeChild($fruits.lastElementChild);
  </script>
</html>

🌺 39.7 μ–΄νŠΈλ¦¬λ·°νŠΈ

βœ” 39.7.1 μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œμ™€ attributes ν”„λ‘œνΌν‹°

HTML λ¬Έμ„œμ˜ κ΅¬μ„±μš”μ†ŒμΈ HTML μš”μ†ŒλŠ” μ—¬λŸ¬ 개의 μ–΄νŠΈλ¦¬λ·°νŠΈ(속성)λ₯Ό κ°€μ§ˆ 수 μžˆλ‹€.

<input id="user" type="text" value="ungmo2">

HTML λ¬Έμ„œκ°€ νŒŒμ‹±λ  λ•Œ HTML μš”μ†Œμ˜ μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œλ‘œ λ³€ν™˜λ˜μ–΄ μš”μ†Œ λ…Έλ“œμ™€ μ—°κ²°λœλ‹€. μ΄λ•Œ HTML μ–΄νŠΈλ¦¬λ·°νŠΈλ‹Ή ν•˜λ‚˜μ˜ μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œκ°€ μƒμ„±λœλ‹€. 즉, μœ„ input μš”μ†ŒλŠ” 3개의 μ–΄νŠΈλ¦¬λ·°νŠΈκ°€ μžˆμœΌλ―€λ‘œ 3개의 μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œκ°€ μƒμ„±λœλ‹€.

μ΄λ•Œ λͺ¨λ“  μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œμ˜ μ°Έμ‘°λŠ” μœ μ‚¬ λ°°μ—΄ 객체이자 μ΄ν„°λŸ¬λΈ”μΈ NameNodeMap 객체에 λ‹΄κ²¨μ„œ μš”μ†Œ λ…Έλ“œμ˜ attributes ν”„λ‘œνΌν‹°μ— μ €μž₯λœλ‹€.

βœ” 39.7.2 HTML μ–΄νŠΈλ¦¬λ·°νŠΈ μ‘°μž‘

HTML μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 μ°Έμ‘°ν•˜λ €λ©΄ Element.prototype.getAttribute(attributeName) 값을 λ³€κ²½ν•˜λ €λ©΄ Element.prototype.setAttribute(attributeName,attributeValue) λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€.

<!DOCTYPE html>
<html>
<body>
  <input id="user" type="text" value="ungmo2">
  <script>
    const $input = document.getElementById('user');

    // value μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 취득
    const inputValue = $input.getAttribute('value');
    console.log(inputValue); // ungmo2

    // value μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 λ³€κ²½
    $input.setAttribute('value', 'foo');
    console.log($input.getAttribute('value')); // foo
  </script>
</body>
</html>

νŠΉμ • HTML μ–΄νŠΈλ¦¬λ·°νŠΈκ°€ μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•˜λ €λ©΄ Element.prototype.hasAttribute(attributeName), νŠΉμ • HTML μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό μ‚­μ œν•˜λ €λ©΄ Element.prototype.removeAttribute(attributeName) λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€.

<!DOCTYPE html>
<html>
<body>
  <input id="user" type="text" value="ungmo2">
  <script>
    const $input = document.getElementById('user');

    // value μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ 쑴재 확인
    if ($input.hasAttribute('value')) {
      // value μ–΄νŠΈλ¦¬λ·°νŠΈ μ‚­μ œ
      $input.removeAttribute('value');
    }

    // value μ–΄νŠΈλ¦¬λ·°νŠΈκ°€ μ‚­μ œλ˜μ—ˆλ‹€.
    console.log($input.hasAttribute('value')); // false
  </script>
</body>
</html>

βœ” 39.7.3 HTML μ–΄νŠΈλ¦¬λ·°νŠΈ vs DOM ν”„λ‘œνΌν‹°

μš”μ†Œ λ…Έλ“œ κ°μ²΄μ—λŠ” HTML μ–΄νŠΈλ¦¬λ·°νŠΈμ— λŒ€μ‘ν•˜λŠ” ν”„λ‘œνΌν‹°(μ΄ν•˜ DOM ν”„λ‘œνΌν‹°)κ°€ μ‘΄μž¬ν•œλ‹€. 이 DOM ν”„λ‘œνΌν‹°λ“€μ€ HTML μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 μ΄ˆκΈ°κ°’μœΌλ‘œ 가지고 μžˆλ‹€.

HTML μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ 역할은 HTML μš”μ†Œμ˜ 초기 μƒνƒœλ₯Ό μ§€μ •ν•˜λŠ” 것이닀. 즉 HTML μ–΄νŠΈλ¦¬λ·°νŠΈ 값은 HTML μš”μ†Œμ˜ 초기 μƒνƒœλ₯Ό μ˜λ―Έν•˜λ©° μ΄λŠ” λ³€ν•˜μ§€ μ•ŠλŠ”λ‹€.

μš”μ†Œ λ…Έλ“œλŠ” μƒνƒœ(state)λ₯Ό 가지고 μžˆλ‹€. μš”μ†Œ λ…Έλ“œλŠ” 초기 μƒνƒœμ™€ μ΅œμ‹  μƒνƒœ 즉, 2개의 μƒνƒœλ₯Ό 관리해야 ν•œλ‹€. μš”μ†Œ λ…Έλ“œμ˜ 초기 μƒνƒœλŠ” μ–΄νŠΈλ¦¬λ·°νŠΈ λ…ΈνŠΈκ°€ κ΄€λ¦¬ν•˜λ©°, μš”μ†Œ λ…Έλ“œμ˜ μ΅œμ‹  μƒνƒœλŠ” DOM ν”„λ‘œνΌν‹°κ°€ κ΄€λ¦¬ν•œλ‹€.

  • μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œ HTML μ–΄νŠΈλ¦¬λ·°νŠΈλ‘œ μ§€μ •ν•œ HTML μš”μ†Œμ˜ 초기 μƒνƒœλŠ” μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œμ—μ„œ κ΄€λ¦¬ν•œλ‹€. μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œμ—μ„œ κ΄€λ¦¬ν•˜λŠ” μ–΄νŠΈλ¦¬λ·°νŠΈ 값은 μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•΄ μƒνƒœκ°€ λ³€κ²½λ˜μ–΄λ„ λ³€ν•˜μ§€ μ•Šκ³  HTML μ–΄νŠΈλ¦¬λ·°νŠΈλ‘œ μ§€μ •ν•œ HTML μš”μ†Œμ˜ 초기 μƒνƒœλ₯Ό κ·ΈλŒ€λ‘œ μœ μ§€ν•œλ‹€. μ–΄νŠΈλ¦¬λ·°νŠΈ λ…Έλ“œκ°€ κ΄€λ¦¬ν•˜λŠ” 초기 μƒνƒœ 값을 μ·¨λ“ν•˜κ±°λ‚˜ λ³€κ²½ν•˜λ €λ©΄ getAttribute/setAttribute λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€. getAttribute λ©”μ„œλ“œλ‘œ μ·¨λ“ν•œ 값은 초기 μƒνƒœ 값이닀. HTML μš”μ†Œμ— μ§€μ •ν•œ μ–΄νŠΈλ¦¬λ·°νŠΈ 값은 μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•΄ λ³€ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ μ–Έμ œλ‚˜ λ™μΌν•˜λ‹€. setAttribute λ©”μ„œλ“œλŠ” 초기 μƒνƒœ 값을 λ³€κ²½ν•œλ‹€.
  • DOM ν”„λ‘œνΌν‹°
    μ‚¬μš©μžκ°€ μž…λ ₯ν•œ μ΅œμ‹  μƒνƒœλŠ” HTML μ–΄νŠΈλ¦¬λ·°νŠΈμ— λŒ€μ‘ν•˜λŠ” μš”μ†Œ λ…Έλ“œμ˜ DOM ν”„λ‘œνΌν‹°κ°€ κ΄€λ¦¬ν•œλ‹€. DOM ν”„λ‘œνΌν‹°λŠ” μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•œ μƒνƒœ 변화에 λ°˜μ‘ν•˜μ—¬ μ–Έμ œλ‚˜ μ΅œμ‹  μƒνƒœλ₯Ό μœ μ§€ν•œλ‹€.
    DOM ν”„λ‘œνΌν‹°λ‘œ μ·¨λ“ν•œ 값은 HTML μš”μ†Œμ˜ μ΅œμ‹  μƒνƒœ 값을 μ˜λ―Έν•œλ‹€. 이 μ΅œμ‹  μƒνƒœ 값은 μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•΄ μ–Έμ œλ“ μ§€ λ™μ μœΌλ‘œ λ³€κ²½λ˜μ–΄ μ΅œμ‹  μƒνƒœλ₯Ό μœ μ§€ν•œλ‹€.
    ```jsx
    <!DOCTYPE html>
    <html>
    <body>
      <input id="user" type="text" value="ungmo2">
      <script>
        const $input = document.getElementById('user');
    
        // μ‚¬μš©μžκ°€ input μš”μ†Œμ˜ μž…λ ₯ ν•„λ“œμ— 값을 μž…λ ₯ν•  λ•Œλ§ˆλ‹€ input μš”μ†Œ λ…Έλ“œμ˜
        // value ν”„λ‘œνΌν‹° κ°’, 즉 μ΅œμ‹  μƒνƒœ 값을 μ·¨λ“ν•œλ‹€. value ν”„λ‘œνΌν‹° 값은 μ‚¬μš©μžμ˜ μž…λ ₯에
        // μ˜ν•΄ λ™μ μœΌλ‘œ λ³€κ²½λœλ‹€.
        $input.oninput = () => {
          console.log('value ν”„λ‘œνΌν‹° κ°’', $input.value);
        };
    
        // getAttribute λ©”μ„œλ“œλ‘œ μ·¨λ“ν•œ HTML μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’, 즉 초기 μƒνƒœ 값은 λ³€ν•˜μ§€ μ•Šκ³  μœ μ§€λœλ‹€.
        console.log('value μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’', $input.getAttribute('value'));
      </script>
    </body>
    </html>
    ```
    
    이처럼 **HTML μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” HTML μš”μ†Œμ˜ 초기 μƒνƒœ 값을 κ΄€λ¦¬ν•˜κ³  DOM ν”„λ‘œνΌν‹°λŠ” μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•΄ λ³€κ²½λ˜λŠ” μ΅œμ‹  μƒνƒœλ₯Ό 관리**ν•œλ‹€. 단, λͺ¨λ“  DOM ν”„λ‘œνΌν‹°κ°€ μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•΄ λ³€κ²½ μ΅œμ‹ μƒνƒœλ₯Ό κ΄€λ¦¬ν•˜λŠ”κ²ƒμ€ μ•„λ‹ˆλ‹€**. μ‚¬μš©μžμ˜ μž…λ ₯에 μ˜ν•œ μƒνƒœ 변화와 κ΄€κ³„μžˆλŠ” DOM ν”„λ‘œνΌν‹°λ§Œ μ΅œμ‹  μƒνƒœ 값을 관리**ν•œλ‹€.
  • HTML μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ DOM ν”„λ‘œνΌν‹°μ˜ λŒ€μ‘ 관계 λŒ€λΆ€λΆ„μ˜ HTML μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” HTML μ–΄νŠΈλ¦¬λ·°νŠΈ 이름과 λ™μΌν•œ DOM ν”„λ‘œνΌν‹°μ™€ 1:1둜 λŒ€μ‘ν•œλ‹€. 단, λ‹€μŒκ³Ό 같이 HTML μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ DOM ν”„λ‘œνΌν‹°κ°€ μ–Έμ œλ‚˜ 1:1둜 λŒ€μ‘ν•˜λŠ” 것은 μ•„λ‹ˆλ©°, HTML μ–΄νŠΈλ¦¬λ·°νŠΈ 이름과 DOM ν”„λ‘œνΌν‹° ν‚€κ°€ λ°˜λ“œμ‹œ μΌμΉ˜ν•˜λŠ” 것도 μ•„λ‹ˆλ‹€.
    • id μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ id ν”„λ‘œνΌν‹°λŠ” 1:1둜 λŒ€μ‘ν•˜λ©°, λ™μΌν•œ κ°’μœΌλ‘œ μ—°λ™ν•œλ‹€.
    • input μš”μ†Œμ˜ value μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” value ν”„λ‘œνΌν‹°μ™€ 1:1 λŒ€μ‘ν•œλ‹€. ν•˜μ§€λ§Œ value μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” 초기 μƒνƒœλ₯Ό value ν”„λ‘œνΌν‹°λŠ” μ΅œμ‹  μƒνƒœλ₯Ό κ°–λŠ”λ‹€.
    • class μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” className, classList ν”„λ‘œνΌν‹°μ™€ 1:1 λŒ€μ‘ν•œλ‹€.
    • for μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” htmlFor ν”„λ‘œνΌν‹°μ™€ 1:1 λŒ€μ‘ν•œλ‹€.
    • td μš”μ†Œμ˜ colspan μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” λŒ€μ‘ν•˜λŠ” ν”„λ‘œνΌν‹°κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€.
    • textContent ν”„λ‘œνΌν‹°λŠ” λŒ€μ‘ν•˜λŠ” μ–΄νŠΈλ¦¬λ·°νŠΈκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€.
    • μ–΄νŠΈλ¦¬λ·°νŠΈ 이름은 λŒ€μ†Œλ¬Έμžλ₯Ό κ΅¬λ³„ν•˜μ§€ μ•Šμ§€λ§Œ λŒ€μ‘ν•˜λŠ” ν”„λ‘œνΌν‹° ν‚€λŠ” 카멜 μΌ€μ΄μŠ€λ₯Ό λ”°λ₯Έλ‹€.(maxlength β†’ maxLength)
  • DOM ν”„λ‘œνΌν‹° κ°’μ˜ νƒ€μž… getAttrivute λ©”μ„œλ“œλ‘œ μ·¨λ“ν•œ μ–΄νŠΈλ¦¬λ·°νŠΈ 값은 μ–Έμ œλ‚˜ λ¬Έμžμ—΄μ΄λ‹€. ν•˜μ§€λ§Œ DOM ν”„λ‘œνΌν‹°λ‘œ μ·¨λ“ν•œ μ΅œμ‹  μƒνƒœ 값은 λ¬Έμžμ—΄μ΄ 아닐 μˆ˜λ„ μžˆλ‹€. 예λ₯Ό λ“€μ–΄, checkbox μš”μ†Œμ˜ μ–΄νŠΈλ¦¬λ·°νŠΈ 값은 λ¬Έμžμ—΄μ΄μ§€λ§Œ checked ν”„λ‘œνΌν‹° 값은 λΆˆλ¦¬μ–Έ νƒ€μž…μ΄λ‹€.
    <!DOCTYPE html>
    <html>
    <body>
      <input type="checkbox" checked>
      <script>
        const $checkbox = document.querySelector('input[type=checkbox]');
    
        // getAttribute λ©”μ„œλ“œλ‘œ μ·¨λ“ν•œ μ–΄νŠΈλ¦¬λ·°νŠΈ 값은 μ–Έμ œλ‚˜ λ¬Έμžμ—΄μ΄λ‹€.
        console.log($checkbox.getAttribute('checked')); // ''
    
        // DOM ν”„λ‘œνΌν‹°λ‘œ μ·¨λ“ν•œ μ΅œμ‹  μƒνƒœ 값은 λ¬Έμžμ—΄μ΄ 아닐 μˆ˜λ„ μžˆλ‹€.
        console.log($checkbox.checked); // true
      </script>
    </body>
    </html>

βœ” 39.7.4 data μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ dataset ν”„λ‘œνΌν‹°

data μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ dataset ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•˜λ©΄ HTML μš”μ†Œμ— μ •μ˜ν•œ μ‚¬μš©μž μ •μ˜ μ–΄νŠΈλ¦¬λ·°νŠΈμ™€ μžλ°”μŠ€ν¬λ¦½νŠΈ 간에 데이터λ₯Ό κ΅ν™˜ν•  수 μžˆλ‹€. data μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” data-user-id, data-roleκ³Ό 같이 data- 접두사 λ‹€μŒμ— μž„μ˜μ˜ 이름을 λΆ™μ—¬ μ‚¬μš©ν•œλ‹€.

data μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ 값은 HTMLElement.dataset ν”„λ‘œνΌν‹°λ‘œ 취득할 수 μžˆλ‹€. dataset ν”„λ‘œνΌν‹°λŠ” HTML μš”μ†Œμ˜ λͺ¨λ“  data μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ 정보λ₯Ό μ œκ³΅ν•˜λŠ” DOMStringMap 객체λ₯Ό λ°˜ν™˜ν•œλ‹€. DOMStringMap κ°μ²΄λŠ” data μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ data-접두사 λ‹€μŒμ— 뢙인 μž„μ˜μ˜ 이름을 카멜 μΌ€μ΄μŠ€λ‘œ λ³€ν™˜ν•œ ν”„λ‘œνΌν‹°λ₯Ό 가지고 μžˆλ‹€. 이 ν”„λ‘œνΌν‹°λ‘œ data μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ 값을 μ·¨λ“ν•˜κ±°λ‚˜ λ³€κ²½ν•  수 μžˆλ‹€.

<!DOCTYPE html>
<html>
<body>
  <ul class="users">
    <li id="1" data-user-id="7621" data-role="admin">Lee</li>
    <li id="2" data-user-id="9524" data-role="subscriber">Kim</li>
  </ul>
  <script>
    const users = [...document.querySelector('.users').children];
    console.log(users)
    // user-idκ°€ '7621'인 μš”μ†Œ λ…Έλ“œλ₯Ό μ·¨λ“ν•œλ‹€.
    const user = users.find(user => user.dataset.userId === '7621');
    // user-idκ°€ '7621'인 μš”μ†Œ λ…Έλ“œμ—μ„œ data-role의 값을 μ·¨λ“ν•œλ‹€.
    console.log(user.dataset.role); // "admin"

    // user-idκ°€ '7621'인 μš”μ†Œ λ…Έλ“œμ˜ data-role 값을 λ³€κ²½ν•œλ‹€.
    user.dataset.role = 'subscriber';
    // dataset ν”„λ‘œνΌν‹°λŠ” DOMStringMap 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.
    console.log(user.dataset); // DOMStringMap {userId: "7621", role: "subscriber"}
  </script>
</body>
</html>

data μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ data- 접두사 λ‹€μŒμ— μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 이름을 ν‚€λ‘œ μ‚¬μš©ν•˜μ—¬ dataset ν”„λ‘œνΌν‹°μ— 값을 ν• λ‹Ήν•˜λ©΄ HTML μš”μ†Œμ— data μ–΄νŠΈλ¦¬λ·°νŠΈκ°€ μΆ”κ°€λœλ‹€. μ΄λ•Œ dataset ν”„λ‘œνΌν‹°μ— μΆ”κ°€ν•œ μΉ΄λ©œμΌ€μ΄μŠ€(fooBar)의 ν”„λ‘œνΌν‹° ν‚€λŠ” data μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ data- 접두사 λ‹€μŒμ— μΌ€λ°₯μΌ€μ΄μŠ€(data-foo-bar)둜 μžλ™ λ³€κ²½λ˜μ–΄ μΆ”κ°€λœλ‹€.

<!DOCTYPE html>
<html>
<body>
  <ul class="users">
    <li id="1" data-user-id="7621">Lee</li>
    <li id="2" data-user-id="9524">Kim</li>
  </ul>
  <script>
    const users = [...document.querySelector('.users').children];

    // user-idκ°€ '7621'인 μš”μ†Œ λ…Έλ“œλ₯Ό μ·¨λ“ν•œλ‹€.
    const user = users.find(user => user.dataset.userId === '7621');

    // user-idκ°€ '7621'인 μš”μ†Œ λ…Έλ“œμ— μƒˆλ‘œμš΄ data μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό μΆ”κ°€ν•œλ‹€.
    user.dataset.role = 'admin';
    console.log(user.dataset);
    /*
    DOMStringMap {userId: "7621", role: "admin"}
    -> <li id="1" data-user-id="7621" data-role="admin">Lee</li>
    */
  </script>
</body>
</html>

🌺 39.8 μŠ€νƒ€μΌ

βœ” 39.8.1 인라인 μŠ€νƒ€μΌ μ‘°μž‘

HTMLElement.prototype.style ν”„λ‘œνΌν‹°λŠ” setter와 getter λͺ¨λ‘ μ‘΄μž¬ν•˜λŠ” μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ‘œμ„œ μš”μ†Œ λ…Έλ“œμ˜ 인라인 μŠ€νƒ€μΌμ„ μ·¨λ“ν•˜κ±°λ‚˜ μΆ”κ°€ λ˜λŠ” λ³€κ²½ν•œλ‹€.

<!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>

style ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•˜λ©΄ CSSStyleDeclaration νƒ€μž…μ˜ 객체λ₯Ό λ°˜ν™˜ν•œλ‹€. CSSStyle.Declaration κ°μ²΄λŠ” λ‹€μ–‘ν•œ CSS ν”„λ‘œνΌν‹°μ— λŒ€μ‘ν•˜λŠ” ν”„λ‘œνΌν‹°λ₯Ό 가지고 있으며, 이 ν”„λ‘œνΌν‹°μ— 값을 ν• λ‹Ήν•˜λ©΄ ν•΄λ‹Ή CSSS ν”„λ‘œνΌν‹°κ°€ 인라인 μŠ€νƒ€μΌλ‘œ HTML μš”μ†Œμ— μΆ”κ°€λ˜κ±°λ‚˜ λ³€κ²½λœλ‹€.

CSS ν”„λ‘œνΌν‹°λŠ” μΌ€λ°₯ μΌ€μ΄μŠ€λ₯Ό λ”°λ₯Έλ‹€. 이에 λŒ€μ‘ν•˜λŠ” CSSStyleDeclaration객체의 ν”„λ‘œνΌν‹°λŠ” 카멜 μΌ€μ΄μŠ€λ₯Ό λ”°λ₯Έλ‹€. 예λ₯Ό λ“€μ–΄, CSS ν”„λ‘œνΌν‹° background-color에 λŒ€μ‘ν•˜λŠ” CSSStyleDeclaration 객체의 ν”„λ‘œνΌν‹° backgroundColor이닀.

$div.style.backgroundColor = 'yellow';
$div.style['background-color'] = 'yellow';
$div.style.width = '100px';

μΌ€λ°₯ μΌ€μ΄μŠ€μ˜ CSSν”„λ‘œνΌν‹°λ₯Ό κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜λ €λ©΄ 객체의 λ§ˆμΉ¨ν‘œ ν‘œκΈ°λ²• λŒ€μ‹  λŒ€κ΄„ν˜Έ ν‘œκΈ°λ²•μ„ μ‚¬μš©ν•œλ‹€. λ‹¨μœ„μ§€μ •μ΄ ν•„μš”ν•œ CSS ν”„λ‘œνΌν‹°μ˜ 값은 λ°˜λ“œμ‹œ λ‹¨μœ„λ₯Ό 지정해야 ν•œλ‹€.

βœ” 39.8.2 클래슀 μ‘°μž‘

.으둜 μ‹œμž‘ν•˜λŠ” 클래슀 μ„ νƒμžλ₯Ό μ‚¬μš©ν•˜μ—¬ CSS classλ₯Ό 미리 μ •μ˜ν•œ λ‹€μŒ, HTML μš”μ†Œμ˜ class μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 λ³€κ²½ν•˜μ—¬ HTML μš”μ†Œμ˜ μŠ€νƒ€μΌμ„ λ³€κ²½ν•  μˆ˜λ„ μžˆλ‹€. μ΄λ•Œ HTML μš”μ†Œμ˜ class μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό μ‘°μž‘ν•˜λ €λ©΄ ckass μ–΄νŠΈλ¦¬λ·°νŠΈμ— λŒ€μ‘ν•˜λŠ” μš”μ†Œ λ…Έλ“œμ˜ DOM ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•œλ‹€. 단, class μ–΄νŠΈλ¦¬λ·°νŠΈμ— λŒ€μ‘ν•˜λŠ” DOM ν”„λ‘œνΌν‹°λŠ” classκ°€ μ•„λ‹ˆλΌ classNameκ³Ό classListλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ classλŠ” μ˜ˆμ•½μ–΄κΈ° λ•Œλ¬Έμ΄λ‹€.

  • className Element.prototype.className ν”„λ‘œνΌν‹°λŠ” setter와 getter λͺ¨λ‘ μ‘΄μž¬ν•˜λŠ” μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ‘œμ„œ HTML μš”μ†Œμ˜ class μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 μ·¨λ“ν•˜κ±°λ‚˜ λ³€κ²½ν•œλ‹€. μš”μ†Œ λ…Έλ“œμ˜ className ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•˜λ©΄ class μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 λ¬Έμžμ—΄λ‘œ λ°˜ν™˜ν•˜κ³ , μš”μ†Œ λ…Έλ“œμ˜ className ν”„λ‘œνΌν‹°μ— λ¬Έμžμ—΄μ„ ν• λ‹Ήν•˜λ©΄ class μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 ν• λ‹Ήν•œ λ¬Έμžμ—΄λ‘œ λ³€κ²½ν•œλ‹€.
    <!DOCTYPE html>
    <html>
    <head>
      <style>
        .box {
          width: 100px; height: 100px;
          background-color: antiquewhite;
        }
        .red { color: red; }
        .blue { color: blue; }
      </style>
    </head>
    <body>
      <div class="box red">Hello World</div>
      <script>
        const $box = document.querySelector('.box');
    
        // .box μš”μ†Œμ˜ class μ–΄νŠΈλ¦¬λ·°νŠΈ 값을 취득
        console.log($box.className); // 'box red'
    
        // .box μš”μ†Œμ˜ class μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’ μ€‘μ—μ„œ 'red'만 'blue'둜 λ³€κ²½
        $box.className = $box.className.replace('red', 'blue');
      </script>
    </body>
    </html><!DOCTYPE html>
    <html>
    <head>
      <style>
        .box {
          width: 100px; height: 100px;
          background-color: antiquewhite;
        }
        .red { color: red; }
        .blue { color: blue; }
      </style>
    </head>
    <body>
      <div class="box red">Hello World</div>
      <script>
        const $box = document.querySelector('.box');
    
        // .box μš”μ†Œμ˜ class μ–΄νŠΈλ¦¬λ·°νŠΈ 정보λ₯Ό 담은 DOMTokenList 객체λ₯Ό 취득
        // classListκ°€ λ°˜ν™˜ν•˜λŠ” DOMTokenList κ°μ²΄λŠ” HTMLCollectionκ³Ό NodeList와 같이
        // λ…Έλ“œ 객체의 μƒνƒœ λ³€ν™”λ₯Ό μ‹€μ‹œκ°„μœΌλ‘œ λ°˜μ˜ν•˜λŠ” μ‚΄μ•„ μžˆλŠ”(live) 객체닀.
        console.log($box.classList);
        // DOMTokenList(2) [length: 2, value: "box blue", 0: "box", 1: "blue"]
    
        // .box μš”μ†Œμ˜ class μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’ μ€‘μ—μ„œ 'red'만 'blue'둜 λ³€κ²½
        $box.classList.replace('red', 'blue');
      </script>
    </body>
    </html>
    className ν”„λ‘œνΌν‹°λŠ” λ¬Έμžμ—΄μ„ λ°˜ν™˜ν•˜λ―€λ‘œ 곡백으둜 κ΅¬λΆ„λœ μ—¬λŸ¬ 개의 클래슀λ₯Ό λ°˜ν™˜ν•˜λŠ” 경우 닀루기가 λΆˆνŽΈν•˜λ‹€.
  • classList Element.prototype.classList ν”„λ‘œνΌν‹°λŠ” class μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ 정보λ₯Ό 담은 DOMTokenList 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.
    <!DOCTYPE html>
    <html>
    <head>
      <style>
        .box {
          width: 100px; height: 100px;
          background-color: antiquewhite;
        }
        .red { color: red; }
        .blue { color: blue; }
      </style>
    </head>
    <body>
      <div class="box red">Hello World</div>
      <script>
        const $box = document.querySelector('.box');
    
        // .box μš”μ†Œμ˜ class μ–΄νŠΈλ¦¬λ·°νŠΈ 정보λ₯Ό 담은 DOMTokenList 객체λ₯Ό 취득
        // classListκ°€ λ°˜ν™˜ν•˜λŠ” DOMTokenList κ°μ²΄λŠ” HTMLCollectionκ³Ό NodeList와 같이
        // λ…Έλ“œ 객체의 μƒνƒœ λ³€ν™”λ₯Ό μ‹€μ‹œκ°„μœΌλ‘œ λ°˜μ˜ν•˜λŠ” μ‚΄μ•„ μžˆλŠ”(live) 객체닀.
        console.log($box.classList);
        // DOMTokenList(2) [length: 2, value: "box blue", 0: "box", 1: "blue"]
    
        // .box μš”μ†Œμ˜ class μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’ μ€‘μ—μ„œ 'red'만 'blue'둜 λ³€κ²½
        $box.classList.replace('red', 'blue');
      </script>
    </body>
    </html>
    DOMTokenList κ°μ²΄λŠ” class μ–΄νŠΈλ¦¬λ·°νŠΈμ˜ 정보λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μ»¬λ ‰μ…˜ κ°μ²΄λ‘œμ„œ μœ μ‚¬ λ°°μ—΄ κ°μ²΄μ΄λ©΄μ„œ μ–΄ν‹°λŸ¬λΈ”μ΄λ‹€. DOMTokenList κ°μ²΄λŠ” λ‹€μŒκ³Ό 같이 μœ μš©ν•œ λ©”μ„œλ“œλ“€μ„ μ œκ³΅ν•œλ‹€.
    • add(…className) add λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬ν•œ 1개 μ΄μƒμ˜ λ¬Έμžμ—΄μ„ class μ–΄νŠΈλ¦¬λ·°νŠΈ κ°’μœΌλ‘œ μΆ”κ°€ν•œλ‹€.
      $box.classList.add('foo'); // -> class="box red foo"
      $box.classList.add('bar', 'baz'); // -> class="box red foo bar baz"
    • remove(…className)
      remove λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬ν•œ 1개 μ΄μƒμ˜ λ¬Έμžμ—΄κ³Ό μΌμΉ˜ν•˜λŠ” 클래슀λ₯Ό class μ–΄νŠΈλ¦¬λ·°νŠΈμ—μ„œ μ‚­μ œν•œλ‹€. 인수둜 μ „λ‹¬ν•œ λ¬Έμžμ—΄κ³Ό μΌμΉ˜ν•˜λŠ” ν΄λž˜μŠ€κ°€ class μ–΄νŠΈλ¦¬λ·°νŠΈμ— μ—†μœΌλ©΄ μ—λŸ¬ 없이 λ¬΄μ‹œλœλ‹€.
      ```jsx
      $box.classList.remove('foo'); // -> class="box red bar baz"
      $box.classList.remove('bar', 'baz'); // -> class="box red"
      $box.classList.remove('x'); // -> class="box red"
      ```
    • item(index) item λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬ν•œ index에 ν•΄λ‹Ήν•˜λŠ” 클래슀λ₯Ό class μ–΄νŠΈλ¦¬λ·°νŠΈμ—μ„œ λ°˜ν™˜ν•œλ‹€. 예λ₯Όλ“€μ–΄ indexκ°€ 0이면 첫 번째 클래슀λ₯Ό λ°˜ν™˜ν•˜κ³  indexκ°€ 1이면 두 번째 클래슀λ₯Ό λ°˜ν™˜ν•œλ‹€.
      $box.classList.item(0); // -> "box"
      $box.classList.item(1); // -> "red"
    • contains(className) contains λ©”μ„œλ“œλŠ” 인수둜 μ „λ‹¬ν•œ λ¬Έμžμ—΄κ³Ό μΌμΉ˜ν•˜λŠ” ν΄λž˜μŠ€κ°€ class μ–΄νŠΈλ¦¬λ·°νŠΈμ— ν¬ν•¨λ˜μ–΄ μžˆλŠ”μ§€ ν™•μΈν•œλ‹€.
      $box.classList.contains('box');  // -> true
      $box.classList.contains('blue'); // -> false
    • replace(oleClassName, newClassName) replace λ©”μ„œλ“œλŠ” class μ–΄νŠΈλ¦¬λ·°νŠΈμ—μ„œ 첫 번째 인수둜 μ „λ‹¬ν•œ λ¬Έμžμ—΄μ„ 두 번쨰 인수둜 μ „λ‹¬ν•œ λ¬Έμžμ—΄λ‘œ λ³€κ²½ν•œλ‹€.
      $box.classList.replace('red', 'blue'); // -> class="box blue"
    • toggle(className[.force]) toggle λ©”μ„œλ“œλŠ” class μ–΄νŠΈλ¦¬λ·°νŠΈμ— 인수둜 μ „λ‹¬ν•œ λ¬Έμžμ—΄κ³Ό μΌμΉ˜ν•˜λŠ” ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•˜λ©΄ μ œκ±°ν•˜κ³ , μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©΄ μΆ”κ°€ν•œλ‹€.
      $box.classList.toggle('foo'); // -> class="box blue foo"
      $box.classList.toggle('foo'); // -> class="box blue"
      두 번째 인수둜 λΆˆλ¦¬μ–Έ κ°’μœΌλ‘œ ν‰κ°€λ˜λŠ” 쑰건식을 전달할 수 μžˆλ‹€. μ΄λ•Œ μ‘°κ±΄μ‹μ˜ 평가 κ²°κ³Όκ°€ true이면 class μ–΄νŠΈλ¦¬λ·°νŠΈμ— κ°•μ œλ‘œ 첫 번째 인수둜 전달받은 λ¬Έμžμ—΄μ„ μΆ”κ°€ν•˜κ³ , false이면 class μ–΄νŠΈλ¦¬λ·°νŠΈμ—μ„œ κ°•μ œλ‘œ 첫 번쨰 인수둜 전달받은 λ¬Έμžμ—΄μ„ μ œκ±°ν•œλ‹€.
      // class μ–΄νŠΈλ¦¬λ·°νŠΈμ— κ°•μ œλ‘œ 'foo' 클래슀λ₯Ό μΆ”κ°€
      $box.classList.toggle('foo', true); // -> class="box blue foo"
      // class μ–΄νŠΈλ¦¬λ·°νŠΈμ—μ„œ κ°•μ œλ‘œ 'foo' 클래슀λ₯Ό 제거
      $box.classList.toggle('foo', false); // -> class="box blue"

βœ” 39.8.3 μš”μ†Œμ— μ μš©λ˜μ–΄ μžˆλŠ” CSS μŠ€νƒ€μΌ μ°Έμ‘°

style ν”„λ‘œνΌν‹°λŠ” 인라인 μŠ€νƒ€μΌλ§Œ λ°˜ν™˜ν•œλ‹€. λ”°λΌμ„œ 클래슀λ₯Ό μ μš©ν•œ μŠ€νƒ€μΌμ΄λ‚˜ 상속을 톡해 μ•”λ¬΅μ μœΌλ‘œ 적용된 μŠ€νƒ€μΌμ€ style ν”„λ‘œνΌν‹°λ‘œ μ°Έμ‘°ν•  수 μ—†λ‹€. HTML μš”μ†Œμ— μ μš©λ˜μ–΄ μžˆλŠ” λͺ¨λ“  CSS μŠ€νƒ€μΌμ„ μ°Έμ‘°ν•΄μ•Ό ν•  경우 getComputedStyle λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€.

window.getComputedStyle(element[, pseudo]) λ©”μ„œλ“œλŠ” 첫 번째 인수(element)둜 μ „λ‹¬ν•œ μš”μ†Œ λ…Έλ“œμ— μ μš©λ˜μ–΄ μžˆλŠ” ν‰κ°€λœ μŠ€νƒ€μΌμ„ CSSStyleDeclaration 객체에 λ‹΄μ•„ λ°˜ν™˜ν•œλ‹€.

<!DOCTYPE html>
<html>
<head>
  <style>
    body {
      color: red;
    }
    .box {
      width: 100px;
      height: 50px;
      background-color: cornsilk;
      border: 1px solid black;
    }
  </style>
</head>
<body>
  <div class="box">Box</div>
  <script>
    const $box = document.querySelector('.box');

    // .box μš”μ†Œμ— 적용된 λͺ¨λ“  CSS μŠ€νƒ€μΌμ„ λ‹΄κ³  μžˆλŠ” CSSStyleDeclaration 객체λ₯Ό 취득
    const computedStyle = window.getComputedStyle($box);
    console.log(computedStyle); // CSSStyleDeclaration

    // μž„λ² λ”© μŠ€νƒ€μΌ
    console.log(computedStyle.width); // 100px
    console.log(computedStyle.height); // 50px
    console.log(computedStyle.backgroundColor); // rgb(255, 248, 220)
    console.log(computedStyle.border); // 1px solid rgb(0, 0, 0)

    // 상속 μŠ€νƒ€μΌ(body -> .box)
    console.log(computedStyle.color); // rgb(255, 0, 0)

    // κΈ°λ³Έ μŠ€νƒ€μΌ
    console.log(computedStyle.display); // block
  </script>
</body>
</html>

getComputedStyle λ©”μ„œλ“œμ˜ 두 번째 인수(pseudo)둜 :after, :before와 같은 μ˜μ‚¬ μš”μ†Œλ₯Ό μ§€μ •ν•˜λŠ” λ¬Έμžμ—΄μ„ 전달할 수 μžˆλ‹€. μ˜μ‚¬ μš”μ†Œκ°€ μ•„λ‹Œ 일반 μš”μ†Œμ˜ 경우 두 번째 μΈμˆ˜λŠ” μƒλž΅ν•œλ‹€.

<!DOCTYPE html>
<html>
<head>
  <style>
    .box:before {
      content: 'Hello';
    }
  </style>
</head>
<body>
  <div class="box">Box</div>
  <script>
    const $box = document.querySelector('.box');

    // μ˜μ‚¬ μš”μ†Œ :before의 μŠ€νƒ€μΌμ„ μ·¨λ“ν•œλ‹€.
    const computedStyle = window.getComputedStyle($box, ':before');
    console.log(computedStyle.content); // "Hello"
  </script>
</body>
</html>

🌺 39.9 DOM ν‘œμ€€

DOM은 ν˜„μž¬ λ‹€μŒκ³Ό 같이 4개의 레벨(버전)이 μžˆλ‹€.

λ ˆλ²¨ν‘œμ€€λ¬Έμ„œ URL
DOM Level 1https://www.w3.org/TR/REC-DOM-Level-1
DOM Level 2https://www.w3.org/TR/DOM-Level-2-Core
DOM Level 3https://www.w3.org/TR/DOM-Level-3-Core
DOM Level 4https://dom.spec.whatwg.org
profile
μ΄μ‚¬μ€‘μž…λ‹ˆλ‹€!🌟https://velog.io/@devkyoung2

0개의 λŒ“κΈ€

κ΄€λ ¨ μ±„μš© 정보