모던 JavaScript 튜토리얼 파트 2. 브라우저: 문서, 이벤트, 인터페이스를 읽고 정리, 기록
브라우저는 웹페이지를 만나면 HTML을 읽어(파싱) DOM 객체를 생성한다.
요소 노드(element node)에서 대부분의 표준 HTML 속성은 DOM 객체의 프로퍼티가 된다.
아래와 같이 사용할 수 있다.
<body id=”page”>
body.id = “page”
→ 하지만 항상 1대1로 매핑되지는 않는다.
- 속성 – HTML 안에 쓰임
- 프로퍼티 – DOM 객체 안에 쓰임
DOM 프로퍼티
DOM 프로퍼티는 내장 프로퍼티도 많지만 자신만의 프로퍼티도 만들 수 있다.
DOM 노드는 자바스크립트 객체이다.
document.body에 새로운 프로퍼티, 메서드 만들기
document.body.myData = {
name: 'Caesar',
title: 'Imperator'
};
alert(document.body.myData.title); // Imperator
document.body.sayTagName = function() {
alert(this.tagName);
};
document.body.sayTagName();
// BODY (sayTagName의 'this'엔 document.body가 저장됨)
내장 프로토타입을 수정하여 모든 요소 노드에서 메서드 사용하게 하기
Element.prototype.sayHi = function() {
alert(`Hello, I'm ${this.tagName}`);
};
document.documentElement.sayHi(); // Hello, I'm HTML
document.body.sayHi(); // Hello, I'm BODY
HTML 속성
HTML에서 태그는 복수의 속성을 가질 수 있다.
브라우저는 HTML을 파싱해 DOM 객체를 만들 때 HTML 표준 속성으로 DOM 프로퍼티를 만든다.
- 표준이 아닌 속성일 때는 프로퍼티로 전환되지 않아 undefined 가 뜰 수 있다.
<body id="test" something="non-standard">
<script>
alert(document.body.id); // test
// 비표준 속성은 프로퍼티로 전환되지 않습니다.
alert(document.body.something); // undefined
</script>
</body>
요소마다 표준 속성이 다르기 때문에 주의해야 한다.
"type"은 <input> 요소(HTMLInputElement)에선 표준이지만,
<body>(HTMLBodyElement)에선 아니다.
<body id="body" type="...">
<input id="input" type="text">
<script>
alert(input.type);
// text
alert(body.type);
// type은 body의 표준 속성이 아니므로 DOM 프로퍼티가 생성되지 않아 undefined 출력
</script>
</body>
비표준 속성에 접근할 수 있는 방법
모든 속성은 아래의 메서드를 사용해 접근할 수 있다.
- elem.hasAttribute(name) - 속성 존재 여부 확인
- elem.getAttribute(name) - 속성값을 가져옴
- elem.setAttribute(name, value) - 속성값을 변경함
- elem.removeAttribute(name) - 속성값을 지움
- elem.attributes - 모든 속성값을 읽음
- 내장 클래스 Attr를 구현한 객체들을 담은 컬렉션을 반환
- 객체엔 name과 value 프로퍼티가 존재한다.
<body something="non-standard">
<script>
alert(document.body.getAttribute('something')); // 비표준 속성에 접근
</script>
</body>
HTML 속성의 특징
대소문자를 가리지 않는다.
값은 항상 문자열이다.
- 예시)
<body>
<div id="elem" about="Elephant"></div>
<script>
alert( elem.getAttribute('About') ); // (1) 'Elephant', 속성 읽기
elem.setAttribute('Test', 123); // (2) 속성 추가하기
alert( elem.outerHTML ); // (3) 추가된 속성 확인하기
for (let attr of elem.attributes) { // (4) 속성 전체 나열하기
alert( `${attr.name} = ${attr.value}` );
}
</script>
</body>
프로퍼티 - 속성 동기화
표준 속성이 변하면 대응하는 프로퍼티는 자동으로 갱신된다.
일부를 제외하고 프로퍼티가 변하면 속성 역시 갱신된다.
= 속성 ↔ 프로퍼티 간 갱신이 일어난다.
input.value 처럼 동기화가 속성 → 프로퍼티 방향으로만 일어나는 예외상황도 있다.
<input>
<script>
let input = document.querySelector('input');
// 속성 추가 => 프로퍼티 갱신
input.setAttribute('value', 'text');
alert(input.value); // text (갱신)
// 프로퍼티를 변경해도 속성이 갱신되지 않음
input.value = 'newValue';
alert(input.getAttribute('value')); // text (갱신 안됨!)
</script>
DOM 프로퍼티 값의 타입
DOM 프로퍼티는 항상 문자열은 아니다.
- 체크 박스의 input.checked 프로퍼트는 boolean 값을 가진다.
- style 속성의 경우 문자열이지만, style 프로퍼티는 객체이다.
<div id="div" style="color:red;font-size:120%">Hello</div>
<script>
// string
alert(div.getAttribute('style')); // color:red;font-size:120%
// object
alert(div.style); // [object CSSStyleDeclaration]
alert(div.style.color); // red
</script>
DOM 프로퍼티 값이 문자열이더라도 속성값과 다른 경우도 있다.
- href 속성이 상대 URL이나 #hash 이더라도 href 프로퍼티엔 항상 URL 전체가 저장되는 경우
link
// 속성
alert(a.getAttribute('href')); // #hello
// 프로퍼티
alert(a.href ); // 실행되는 사이트 주소에 따라 <<a href=http://site.com/page#hello>http://site.com/page#hello</a>> 형태로 값이 저장됨
비표준 속성, dataset
비표준 속성은 사용자가 직접 지정한 데이터를 HTML에서 자바스크립트로 넘기고 싶은 경우나 자바스크립트를 사용해 조작할 HTML 요소를 표시하기 위해 사용할 수 있다.
<!-- 이름(name) 정보를 보여주는 div라고 표시 -->
<div show-info="name"></div>
<!-- 나이(age) 정보를 보여주는 div라고 표시 -->
<div show-info="age"></div>
<script>
// 표시한 요소를 찾고, 그 자리에 원하는 정보를 보여주는 코드
let user = {
name: "Pete",
age: 25
};
for(let div of document.querySelectorAll('[show-info]')) {
// 원하는 정보를 필드 값에 입력해 줌
let field = div.getAttribute('show-info');
div.innerHTML = user[field]; // Pete가 'name'에, 25가 'age'에 삽입됨
}
</script>
요소에 스타일을 적용할 때 사용할 수도 있다.
주문 상태(order state)를 나타내는 커스텀 속성 order-state를 사용해 주문 상태에 따라 스타일을 변경
<style>
/* 스타일이 커스텀 속성 'order-state'에 따라 변합니다. */
.order[order-state="new"] {
color: green;
}
.order[order-state="pending"] {
color: blue;
}
.order[order-state="canceled"] {
color: red;
}
</style>
<div class="order" order-state="new">
A new order.
</div>
<div class="order" order-state="pending">
A pending order.
</div>
<div class="order" order-state="canceled">
A canceled order.
</div>
커스텀 속성의 문제점
비표준 속성을 사용해 코드를 작성했는데 나중에 속성이 표준으로 등록되게 될 수도 있다.
이런 충돌 상황을 방지하기 위한 속성인 data-* 가 있다.
'data-'로 시작하는 속성 전체는 개발자가 용도에 맞게 사용하도록 별도로 예약된다.
dataset 프로퍼티를 사용하면 이 속성에 접근할 수 있다.
- 예시) 요소 elem에 이름이 data-about 인 속성이 있다면 elem.dataset.about 을 사용해 값을 얻을 수 있다.
<body data-about="Elephants">
<script>
alert(document.body.dataset.about); // Elephants
</script>
data-order-state 같이 여러 단어로 구성된 속성은 카멜 표기법(camel-cased)을 사용해 dataset.orderState으로 변환된다.
- 예시)
<style>
.order[data-order-state="new"] {
color: green;
}
.order[data-order-state="pending"] {
color: blue;
}
.order[data-order-state="canceled"] {
color: red;
}
</style>
<div id="order" class="order" data-order-state="new">
A new order.
</div>
<script>
// 읽기
alert(order.dataset.orderState); // new
// 수정하기
order.dataset.orderState = "pending"; // (*)
</script>
data-* 속성은 커스텀 데이터를 안전하고 유효하게 전달한다.
data-* 속성을 사용하면 읽기 뿐만 아니라 수정도 가능하다.
- 속성이 수정되면 CSS가 해당 뷰를 자동으로 업데이트
- 위 예시에서 (*)로 표시한 줄에서 색이 파란색으로 변경됨
'FE' 카테고리의 다른 글
1.8 스타일과 클래스 (0) | 2024.11.16 |
---|---|
1.7 문서 수정하기 (4) | 2024.11.15 |
1.5 주요 노드 프로퍼티 (2) (1) | 2024.11.13 |
1.5 주요 노드 프로퍼티 (1) (0) | 2024.11.12 |
1.4 getElement*, querySelector*로 요소 검색하기 (0) | 2024.11.11 |