본문 바로가기

The Web Developer 부트캠프 2023/JS

DOM

getElementById

Document.getElementById() 메서드는 주어진 문자열과 일치하는 id 속성을 가진 요소를 찾고, 이를 나타내는 Element 객체를 반환한다. ID는 문서 내에서 유일해야 하기 때문에 특정 요소를 빠르게 찾을 때 유용하다. 

 

반환 값

주어진 ID와 일치하는 DOM 요소를 나타내는 Element 객체. 문서 내에 주어진 ID가 없으면 null.

 

Document.querySelector() Document.querySelectorAll()과는 달리 getElementById()는 전역 document 객체의 메서드로만 사용할 수 있고, DOM의 다른 객체는 메서드로 가지고 있지 않다. ID 값은 문서 전체에서 유일해야 하며 "국지적"인 버전을 쓸 이유가 없기 때문.

 

문서에 없는 요소 getElementById()가 팀색하지 않는다. 요소를 동적으로 생성해서 ID를 부여하더라도, Node.insertBefore()나 비슷한 메서드로 문서 트리에 삽입해야 getElementById()로 접근할 수 있다.

var element = document.createElement('div');
element.id = 'testqq';
var el = document.getElementById('testqq'); // el이 null!

 


getElementsByTagName & className

document.getElementsByTagName(' ex) p')

document.getClassName(' ex) myclass)

 


querySelector & querySelectorAll

Document.querySelector(css선택자) 는 제공한 선택자 또는 선택자 뭉치와 일치하는 문서 내 첫 번째 Element를 반환한다. 일치하는 요소가 없으면 null을 반환한다.

 

반환 값

제공한 CSS 선택자를 만족하는 첫 번째 Element 객체. 결과가 없다면 null.

선택자를 만족하는 모든 요소의 목록이 필요하다면 querySelectorAll()을 사용한다.

 


 

innerHTML & textContent & innerText

HTMLElement 인터페이스의 innerText 속성은 요소그 자손의 렌더링 된 텍스트 콘텐츠를 나타냅니다. innerText는 사용자가 커서를 이용해 요소의 콘텐츠를 선택하고 클립보드에 복사했을 때 얻을 수 있는 텍스트의 근삿값을 제공한다.

 

Node 인터페이스의 textContent 속성은 노드그 자손의 텍스트 콘텐츠를 표현한다.

innerText 과 textContent의 차이점

  • 기본적으로, innerText는 텍스트의 렌더링 후 모습을 인식할 수 있지만, textContent는 그렇지않다.
  • textContent는 <script> <style> 요소를 포함한 모든 요소의 콘텐츠를 가져옵니다. 반면 innerText는 "사람이 읽을 수 있는" 요소만 처리한다.
  • textContent는 노드의 모든 요소를 반환합니다. 그에 비해 innerText는 스타일링을 고려하며, "숨겨진" 요소의 텍스트는 반환하지 않는다.
    • 또한, innerText의 CSS 고려로 인해, innerText 값을 읽으면 최신 계산값을 반영하기 위해 리플로우가 발생합니다. (리플로우 계산은 비싸므로 가능하면 피해야 한다.)

 

<h3>원본 요소:</h3>
<p id="source">
  <style>#source { color: red; }</style>
아래에서<br>이 글을<br>어떻게 인식하는지 살펴보세요.
  <span style="display:none">숨겨진 글</span>
</p>
<h3>textContent 결과:</h3>
<textarea id="textContentOutput" rows="6" cols="30" readonly>...</textarea>
<h3>innerText 결과:</h3>
<textarea id="innerTextOutput" rows="6" cols="30" readonly>...</textarea>
<script>
const source = document.getElementById('source');
const textContentOutput = document.getElementById('textContentOutput');
const innerTextOutput = document.getElementById('innerTextOutput');

textContentOutput.innerHTML = source.textContent;
innerTextOutput.innerHTML = source.innerText;
</script>

 

원본 요소:

아래에서
이 글을
어떻게 인식하는지 살펴보세요. 숨겨진 글

textContent 결과:

innerText 결과:

 

 

innerHTML 과 textContent의 차이점

Element.innerHTML는 이름 그대로 HTML을 반환한다. 간혹 innerHTML을 사용해 요소의 텍스트를 가져오거나 쓰는 경우가 있지만, HTML로 분석할 필요가 없다는 점에서 textContent의 성능이 더 좋다.

이에 더해, textContent는 XSS 공격 (en-US)의 위험이 없다.

 


Attribute & Property

Attribute 특징 1. 애트리뷰트는 HTML에 의해 정의된다.

<div id="content" name="content-name" custom="custom"/>

<div> 요소는 값이 "content"인 id 애트리뷰트, 값이 "content-name"인 name 애트리뷰트, 값이 "custom"인 custom 애트리뷰트를 가진다.

 

Attribute 특징 2. 애트리뷰트의 타입은 문자열(string)입니다.

위 예제에서 사용된 <div> 요소의 id 애트리뷰트의 타입을 typeof 연산자로 확인하면 string을 반환한다.

const content = document.getElementById("content");

console.log(typeof content.getAttribute("id")); // string
console.log(typeof content["id"]); // string

 

Property 특징 1. 프로퍼티(Property)는 DOM에 존재하며, DOM은 JavaScript의 객체입니다. 따라서, JavaScript에서 일반 객체를 다루는 것처럼 DOM에 프로퍼티를 추가하거나 가져올 수 있으며 프로퍼티의 타입은 모든 타입이 될 수 있다.

<div id="content" name="content-name" custom="custom"/>
const content = document.getElementById("content");

content.newProperty = 100;
console.log(content.newProperty); // 100
console.log(typeof content.newProperty); // number

 

 

Property 특징 2. 사용자 정의 프로퍼티가 아닌 경우 점 표기법 및 대괄호 표기법으로 가져올 수 없다.

<div id="content" name="content-name" custom="custom"/>
const content = document.getElementById("content");

console.log(content.id); // content
console.log(content.name); // undefined
console.log(content.custom); // undefined

console.log(content["id"]); // content
console.log(content["name"]); // undefined
console.log(content["custom"]); // undefined

id, name, class 등과 같은 프로퍼티는 점 표기법 및 대괄호 표기법으로 가져올 수 있지만, custom과 같은 사용자 정의 프로퍼티는 가져올 수 없다.

 

참고로 name 프로퍼티는 <div> 태그에서 기본 애트리뷰트가 아닌 사용자 정의 애트리뷰트로 간주하므로 위 예제에서 undefined를 반환한다. class는 JavaScript에서 예약어이므로 class가 아닌 className을 사용한다.

 

Property 특징 3. 기본 값이 존재하는 애트리뷰트는 값을 변경할 수 없다.

<input id="content" value="test" />
const content = document.getElementById("content");

content.value = "hello";
console.log(content.getAttribute("value")); // test

<input> 태그의 value 애트리뷰트에 값이 존재하므로 JavaScript에서 값을 변경할 수 없다.

 

그 외 차이점

  1. HTML 애트리뷰트는 대소문자를 구분하지 않지만, DOM 프로퍼티는 대소문자를 구분합니다.
  2. HTML 애트리뷰트의 데이터 타입은 항상 문자열이지만, DOM 프로퍼티는 모든 데이터 타입을 가질 수 있습니다.
  3. "data-"로 시작하는 모든 HTML 애트리뷰트는 DOM 프로퍼티의 "dataset"과 매핑됩니다.

https://developer-talk.tistory.com/870


HTMLCollection & NodeList

HTMLCollection

- getElementByTagName()

- getElementByClassName()

 

NodeList

- getElementByName()

- querySelectorAll()

 

차이점 

1. HTMLCollection와 NodeList의 첫 번째 차이점은 HTMLCollection 객체는 <div>, <span>, <p> 등과 같은 요소 노드만 포함하고 NodeList 객체 요소 노드, 속성 노드, 텍스트 노드 등을 포함한다.

2. 두 번째 차이점은 자식 요소 노드를 접근하는 방법이 다르다.

3. HTMLCollection과 NodeList의 가장 큰 차이점은 HTMLCollection은 DOM에 추가된 새로운 요소를 가져오지만, NodeList는 가져오지 못한다.

4. HTMLCollection은 배열이 아니라 배열과 유사한 유사 배열 객체(Array-like Objects)다. 따라서, 각 요소를 접근하려면 for...of 문을 사용해야한다. NodeList는 forEach() 메서드가 존재함. 

 

https://developer-talk.tistory.com/870


ClassList 

 

css에서 style 특성으로 인라인 스타일을 지정할 수 있지만 이 방법같은 경우 많은 스타일을 한 번에 설정할 때 좋은 방법이 아니다.

이때는 css 클래스를 만들어서 그 클래스를 적용하는 것이 낫다. 

js도 똑같이 클래스를 적용해야하는 경우가 흔하다. 

 

클래스를 추가하는 방법에는 여러가지가 있다.

 

1. setAttribute

더보기
<!DOCTYPE html>

<head>
    <style>
        .purple {
            color: purple;
        }
    </style>
</head>

<body>
    <h1 id="h1">H1</h1>

    <script>
        const h1 = document.querySelector('#h1');
        h1.setAttribute('class', 'purple');
    </script>
</body>

</html>

H1

 

setAttribute를 이용해서 class를 적용할 때 단점이 하나 있다.

 

setAttribute를 이용해서 다른 클래스를 적용하는 코드를 하나 더 작성하면 캐스케이딩으로 인해 purple 클래스는 사라지고 그 후에 나온 setAttribute 코드가 적용될 것이다.

이땐 문자열 템플릿 리터럴로 결합해서 작성할 순 있지만 클래스가 여러개가 된다면 코드가 많이 복잡해 질 것이다. 

 

 

2. classList

 

<!DOCTYPE html>

<head>
    <style>
        .purple {
            color: purple;
        }
        .f {
            font-weight: 300;
        }
    </style>
</head>

<body>
    <h2 id="h2">H2</h2> 

    <script>
        const h2 = document.querySelector('#h2');
        h2.classList.add('purple');
        h2.classList.add('f');
    </script>
</body>

</html>

H2

 

classList를 이용하면 클래스를 계속해서 add하여 둘 다 적용시킬 수 있다. 

 

 

 

remove('class')

더보기
<!DOCTYPE html>

<head>
    <style>
        .purple {
            color: purple;
        }
        .f {
            font-weight: 300;
        }
    </style>
</head>

<body>
    <h3 id="h3">H3</h3> 

    <script>
        const h3 = document.querySelector('#h3');
        h3.classList.add('purple');
        h3.classList.add('f');
        h3.classList.remove('purple');
    </script>
</body>

</html>

 

H3

remove를 통해 class를 없앨 수도 있다.

 

 

 

contains('class')

요소에 특정 클래스가 적용되었는지 아닌지 여부를 알 수 없을 때가 많다.

h3.classList.contains('border') // false
h3.classList.contains('f') // true

 

 

toggle('class')

특정 클래스를 끄고 킬 수 있다. 

h3.classList.toggle('purple');
// 위에서 제거했던 purple 클래스를 다시 켜서 활성화됨.

console.log(h3.getAttribute('class'));
// "f purple"

 


계층 이동 (nextSibling, previousSibling, parentElement, children)

 

parentNode

  • 부모 요소를 선택

parentElement

  • parentNode와 같지만 요소 노드만 선택.

childNodes

  • 모든 자식 노드를 선택

children

  • 자식 요소 노드만 선택

firstChild

  • 첫 번째 자식 요소를 선택.

lastChild

  • 마지막 자식 요소를 선택

nextSilbing

  • 다음 형제 요소를 선택

previousSilbing

  • 이전 형제 요소를 선택

firstElementChild

  • 첫 번째 자식 요소 노드를 선택

lastElementChild

  • 마지막 자식 요소 노드를 선택

 

javascript nextSibling nextElementSibling 차이
nextSibling은 공백이든, 텍스트든 가리지 않고 다음에 있는 것을 가져오고, nextElementSibling은 Element(요소)만 갖고온다.
<html>
<div id="a"></div>
nextSibling테스트
<div id="b"></div>
</html>
var aDiv = document.getElementById("a");
console.log(aDiv.nextSibling);    //nextSibling테스트

console.log(aDiv.nextElementSilbing)   //<div id="b"></div>

 

이들 메서드를 이용하여 요소의 위치를 변경할 수도 있다. 예를 들어, parentNode와 insertBefore를 조합하여 요소를 이동시킬 수 있다.
let movedElement = document.getElementById('moved');
let parentElement = document.getElementById('parent');

// 요소를 이동시킵니다.
parentElement.insertBefore(movedElement, parentElement.firstChild);
위 코드는 parent 요소 안에 있는 moved 요소를 parent의 첫 번째 자식 요소로 이동시키는 예시임.
요소의 위치를 변경할 때는, 반드시 이동시키려는 요소가 현재 DOM에 포함되어 있는 요소여야 한다. 이를 확인하기 위해, appendChild 메서드를 이용하여 이동시키려는 요소를 새로운 요소로 추가하는 것이 좋다.
계층 이동 메서드는 DOM 다루기에 매우 유용하며, 요소의 위치를 변경하거나 특정 요소를 찾는 등 다양한 용도로 사용된다.
 

https://newcodingman.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B3%84%EC%B8%B5-%EC%9D%B4%EB%8F%99%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

 


Append & AppendChild

 

Node.appendChild() 메소드는 한 노드를 특정 부모 노드의 자식 노드 리스트 중 마지막 자식으로 붙인다. 만약 주어진 노드가 이미 문서에 존재하는 노드를 참조하고 있다면 appendChild() 메소드는 노드를 현재 위치에서 새로운 위치로 이동시킨다 (문서에 존재하는 노드를 다른 곳으로 붙이기 전에 부모 노드로 부터 지워버릴 필요는 없다.)

이것은 한 노드가 문서상의 두 지점에 동시에 존재할 수 없다는 것을 의미한다. 그래서 만약 노드가 이미 부모를 가지고 있다면 우선 삭제되고 새로운 위치로 이동한다. 또한, Node.appendChild() 메소드는 오로지 node객체만 자식 요소로 추가할 수 있다. 

const divElem = document.createElement('div')
const pElem = document.createElemment('p')

divElem.appendChild(pElem)'

// 결과 : <div><p></p></div>

 

반면 append 메서드는 appendChild와 같이 Node 객체로 자식 요소를 설정할 수 있을 뿐만 아니라, text를 사용할 수도 있다

const div = document.createElement('div');
div.append('hi')

// 결과 : <div>hi</div>

또한 appendChild()와 다르게 append() 메소드는 여러 개의 자식 요소를 추가할 수 있다

const div = document.createElement('div')
const p = document.createElement('p')

document.body.append(div, p, 'hello')

//결과 : <div></div> <p></p> hello

 

 

remove & removeChild 

removeChild 같은 경우 그 특정 요소를 지우는게 아니라 요소에서 자식을 제거하는 방식이다. 

 

<div id="div">im div <b id="divChild">im child of div and bold</b></div>
const div = document.querySelector('#div');
const b = div.firstElementChild;
console.log(b, b.parentElement);
div.removeChild(b);
console.log(b, b.parentElement);

3>
//<b id="divChild">im child of div and bold</b>
//<div id="div">im div </div>

5>
//<b id="divChild">im child of div and bold</b> null

 

좀 더 짧게는 밑의 방식으로도 작성할 수 있다. 

b.parentElement.removeChild(b);

 

이렇게 removeChild로 특정 요소를 제거하려고 하면 번거롭다. 그래서 나온게 remove 메소드이다.

remove는 제거하려는 바로 그 요소에 호출하는 메소드라서 부모나 자식은 신경 쓰지 않아도 된다. 

 

const div = document.querySelector('#div');
const b = div.firstElementChild;
b.remove();
console.log(div.firstElementChild); // null
console.log(b.parentElement); //null

'The Web Developer 부트캠프 2023 > JS' 카테고리의 다른 글

AJAX 와 API  (0) 2023.09.29
비동기식 javascript  (0) 2023.07.23
js DOM 이벤트  (0) 2023.07.06
js 최신 기능들  (1) 2023.06.14
javascript  (0) 2023.06.10