개발자입니다
[비트캠프] 27일차(6주차2일) - Javascript(캡슐화, DOM API: 태그 찾기, 알아내기, 속성 변경, 추가, 변경, 삭제) 본문
[비트캠프] 27일차(6주차2일) - Javascript(캡슐화, DOM API: 태그 찾기, 알아내기, 속성 변경, 추가, 변경, 삭제)
끈기JK 2022. 12. 13. 10:34
객체 - constructor와 생성자
자바스크립트 객체는 자신을 초기화시킨 생성자 정보를 갖고 있다.
// ex04\exam12.html
function Score(name, kor, eng, math) {
this.name = name;
this.kor = kor;
this.eng = eng;
this.math = math;
}
function Member(id, pwd) {
this.id = id;
this.pwd = pwd;
}
function Board(title, content) {
this.title = title;
this.content = content;
}
var obj1 = new Score("홍길동", 100, 100, 100);
var obj2 = new Member("hong", "1111");
var obj3 = new Board("제목", "내용");
console.log(obj1);
console.log(obj2);
console.log(obj3);
console.log("---------------------")
// 객체를 초기화시킨 생성자를 알아내기
// => constructor 프로퍼티를 사용하라!
console.log(obj1.constructor)
console.log(obj2.constructor)
console.log(obj3.constructor)
console.log("---------------------")
// 생성자의 이름?
console.log(obj1.constructor.name)
console.log(obj2.constructor.name)
console.log(obj3.constructor.name)
console.log("---------------------")
객체 - 캡슐화와 클로저 복제 변수
자바스크립트는 접근 범위를 제어하는 문법(private, protected, public, (default))이 없다.
다만 클로저 메모리를 이용하여 흉내 낼 수 있다.
클로저를 이용하는 경우에는 prototype 저장소에 함수를 저장하면 안 된다.
객체가 아닌 클로저에 값을 저장해야 하기 때문에
객체마다 함수를 추가함으로 메모리 낭비가 있다.
function Score(name, kor, eng, math) {
// 외부에서 name, kor, eng, math 값에 접근하지 못하도록
// 객체에 저장하지 않는다.
// 함수에서 사용하는 kor, eng, math 변수는
// 바깥 함수의 로컬 변수이다.
// 바깥 함수의 호출이 끝나더라도 해당 변수를 사용해야 하기 때문에
// 클로저는 별도의 메모리에 복제해 둔다.
this.getName = function () { return name }
this.setName = function (n) { name = n }
this.getKor = function () { return kor }
this.setKor = function (k) { kor = k }
this.getEng = function () { return eng }
this.setEng = function (e) { eng = e }
this.getMath = function () { return math }
this.setMath = function (m) { math = m }
this.sum = function () {
return kor + eng + math
}
this.aver = function () {
return this.sum() / 3
}
}
var s1 = new Score("홍길동", 100, 100, 100);
console.log(s1);
console.log(s1.name) // s1 객체에 name이라는 프로퍼티가 없다. undefined
console.log(s1.getName(), s1.sum(), s1.aver())
s1.setName("임꺽정")
s1.setKor(90)
console.log(s1.getName(), s1.sum(), s1.aver())
// setName()에서 사용한 name 변수와 getName()에서 사용한 name 변수가 같다.
// 결론!
// 바깥 함수를 한 번 호출할 때 생성한 모든 클로저(closure)들은
// 바깥 함수의 로컬 변수 복제본을 공유한다.
//
// 객체에 저장된 값을 직접 접근하지 못하도록 막는 방법:
// - 클로저 메모리에 저장하도록 유도한다.
// - 클로저를 통해서만 조회 및 변경하도록 만든다.
closure와 local 변수 응용
new Score("아규먼트, ...") 하면 ① new 로 빈 객체 생성되고 Score() 생성자로 인해 ② 초기화 된다. 객체에 기본 프로퍼티가 들어가고 closure가 있으므로 closure 메모리가 생성되어 값이 입력된다.
객체 - 프로퍼티의 소속과 사용법
score1 에 sum(), aver() 를 직접 담으면 score2 에서 사용하지 못한다.
// 생성자 정의
function Score(name, kor, eng, math) {
this.name = name;
this.kor = kor;
this.eng = eng;
this.math = math;
}
// 1) 객체 소속 프로퍼티
var score1 = new Score("홍길동", 100, 100, 100);
score1.sum = function() {
return this.kor + this.eng + this.math;
};
score1.aver = function() {
return this.sum() / 3;
};
console.log(score1.sum(), score1.aver());
// 다음 sum()과 aver() 함수는 score1 객체에만 소속된다.
var score2 = new Score("임꺽정", 90, 90, 90);
console.log(score2.sum(), score2.aver());
// score2에 소속된 함수 중에 sum()과 aver()가 없기 때문에 오류가 발생한다.
함수를 prototype에 저장하면 Score 생성자가 초기화 시킨 객체에서 함수를 사용할 수 있다.
// 생성자 정의
function Score(name, kor, eng, math) {
this.name = name;
this.kor = kor;
this.eng = eng;
this.math = math;
}
// 2) 함수의 prototype 소속 프로퍼티
Score.prototype.sum = function() {
return this.kor + this.eng + this.math;
};
Score.prototype.aver = function() {
return this.sum() / 3;
};
// 함수의 prototype 소속 프로퍼티는
// 그 함수가 초기화시킨 객체에 대해 사용할 수 있다.
var score1 = new Score("홍길동", 100, 100, 100);
console.log(score1.sum(), score1.aver());
// score1.sum() 찾기
// --> Score.prototype.sum()
var score2 = new Score("임꺽정", 90, 90, 90);
console.log(score2.sum(), score2.aver());
// score2.sum() 찾기
// --> Score.prototype.sum()
생성자에 함수를 바로 저장하지 않고 따로 지정하면 사용할 수 없다.
// 생성자 정의
function Score(name, kor, eng, math) {
this.name = name;
this.kor = kor;
this.eng = eng;
this.math = math;
}
// 3) 함수 소속 프로퍼티의 잘못된 예
Score.sum = function() {
return this.kor + this.eng + this.math;
};
Score.aver = function() {
return this.sum() / 3;
};
// 함수 소속 프로퍼티는
// 그 함수가 초기화시킨 객체를 통해 사용할 수 없다.
// 즉 객체를 다루는 용도가 아닌 경우,
// 함수 소속 프로퍼티로 만든다.
var score1 = new Score("홍길동", 100, 100, 100);
console.log(score1.sum(), score1.aver()); // 실행 오류!
var score2 = new Score("임꺽정", 90, 90, 90);
console.log(score2.sum(), score2.aver()); // 실행 오류!
함수 프로퍼티와 prototype 프로퍼티
특정 객체에 대해 작업하지 않는 함수를 묶을 때는 객체(함수 객체)에 바로 저장한다.
사용법 : Math.random(), Math.min()
객체명.함수명() 에서 객체명은 변경되지 않는다.
특정 객체의 값을 사용해서 작업을 수행하는 함수를 묶을 때는 생성자의 prototype 에 저장한다.
사용법 : s1.sum(), s2.sum()
객체명.함수명() 에서 객체명은 대상 객체에 따라 바뀐다.
인스턴스를 다루는 함수는 prototype 소속으로 만들고, 인스턴스를 다루지 않는 함수는 생성자에 정의하라.
// 생성자 정의
function Score(name, kor, eng, math) {
this.name = name;
this.kor = kor;
this.eng = eng;
this.math = math;
}
// 4) 함수 소속 프로퍼티의 적절한 예
// => 다음과 같이 특정 객체의 값을 다루는 함수는 prototype 소속으로 만들라!
Score.prototype.sum = function() {
return this.kor + this.eng + this.math;
};
Score.prototype.aver = function() {
return this.sum() / 3;
};
// => 특정 객체를 다루지 않는 경우 함수 소속 프로퍼티로 만들라!
Score.count = 0;
Score.create = function(csv) {
Score.count++;
var values = csv.split(",");
return new Score(values[0], parseInt(values[1]), parseInt(values[2]), parseInt(values[3]));
};
// 함수에 소속된 프로퍼티를 사용할 때는
// 함수 이름을 통해 사용한다.
var score1 = Score.create("홍길동,100,100,100");
var score2 = Score.create("임꺽정,90,90,90,90");
console.log(Score.count);
console.log(score1.sum(), score1.aver());
console.log(score2.sum(), score2.aver());
/*
김가네김밥.체인점수();
김가네김밥.팜플렛();
김가네김밥.체인점수();
김가네김밥.전년도전체지점매출();
var 강남1호점 = new 김가네김밥();
var 강남2호점 = new 김가네김밥();
강남1호점.주문(김밥4개);
강남2호점.주문(김밥4개);
*/
함수의 소속
함수의 소속은 2가지가 있다.
① 객체에 직접 소속
사용법 : 객체.함수명() 로 호출한다. 여기서 객체는 그룹으로서 역할이다. 이런 함수를 호출하기 위해 new Math() 로 객체 생성할 필요 없다.
예) Math.random(), JSON.parse()
② 생성자의 prototype에 소속
사용법 : 객체 먼저 생성 후 obj.함수명() 로 호출한다. 여기서 obj는 함수가 사용하는 데이터로 역할이다.
예) s1.sum(), str1.split(","), arr1.forEach()
생성자와 인스턴스(instance) *instance: 실제적인 예
"Score의 인스턴스" 는 Score() 생성자를 통해 초기화된 객체이다.
*자바에서 인스턴스는 Score 클래스(설계도)에 따라 생성된 메모리
Mozilla 문서 : 인스턴스를 생성하고 사용하는 메서드는 Instance methods 라 한다.
DOM API
HTMLDocument(Document()) 와 document
생성시 다음과 같이 초기화된다.
① Object() 가 초기화한다.
② EventTarget() 가 초기화한다.
③ Node() 가 초기화한다.
④ Document() 가 초기화한다.
document > html > head, body 로 이어지는 구조를 DOM Tree 라 한다.
태그 정보로 객체를 생성한다. 부모/자식 관계로 맺는다. Tree 구조로 관리한다.
DOM API - document 객체
자바스크립트는 태그를 다루는 도구를 제공한다.
그 도구를 "DOM(Document Object Model) API"라 부른다.
document 객체
=> 웹 브라우저에서 기본으로 제공하는 객체이다.
=> 태그를 찾고, 생성하고, 제어하는 함수를 갖고 있다.
=> var document = new HTMLDocument();
// ex05\exam01-0.html
// document의 타입은?
// => 즉 document 객체를 초기화시킨 생성자는?
console.log(document.constructor.name);
// document 객체를 통해 사용할 수 있는 함수나 변수는?
// => HTMLDocument 생성자가 추가한 함수나 변수이다.
// => 어떤 함수와 변수가 있는지 알고 싶다면 문서 보세요.
// => HTMLDocument 생성자의 문서를 보라!
// => 상속 관계
// Document() --> Node() ---> EventTarget() ---> Object()
console.log(document);
console.log(Document.prototype);
// Document()의 함수
console.log(document.createElement); // document ---> Document.prototype
// Node()의 함수
console.log(document.appendChild); // document ---> Document.prototype ---> Node.prototype
// EventTarget()의 함수
console.log(document.addEventListener); // document ---> Document.prototype ---> Node.prototype ---> EventTarget.prototype
// Object()의 함수
console.log(document.toString); // document ---> Document.prototype ---> Node.prototype ---> EventTarget.prototype ---> Object.prototype
DOM API
DOM API 명세서를 이용해
Java에서 구현(implements) 했다. 즉, 자바 언어로 DOM API 규격에 따라 클래스와 메서드를 만들었다.
Javascript에서 구현했다. 즉, Javascript 언어로 DOM API 규격에 따라 객체와 메서드를 만들었다.
각각의 언어마다 HTML 태그를 사용할 수 있도록 구현했다.
→ 프로그램 언어에 상관없이 메서드 사용법이 같다! Javascript의 기술이 아니다.
DOM API - id 값으로 태그 찾기
<h1 id="header1" class="g1">제목1</h1>
<h2 id="header2" class="g1">제목1.1</h2>
<h2 id="header3" class="g1">제목1.2</h2>
<h1 id="header4" class="g2">제목2</h1>
<h2 id="header5" class="g2">제목2.1</h2>
<h2 id="header6" class="g2">제목2.2</h2>
<script>
"use strict"
// Document.prototype.getElementById("태그아이디")
// => 리턴 값: HTMLElement 하위 생성자에 의해 초기화된 객체를 리턴
var e1 = document.getElementById("header4"); // vanilla JS 방식
//var e1 = jQuery("#header4");
//var e1 = $("#header4");
console.log(e1);
console.log(e1.name); // undefined
console.log(e1.localName); // 태그명
console.log(e1.constructor.name); // 객체의 생성자 이름
console.log("----------------------------");
// => 생성자 상속 관계: HTMLHeadingElement() ---> HTMLElement() ---> Element() ---> Node() ---> EventTarget() ---> Object()
console.log(e1 instanceof HTMLHeadingElement); // true
console.log(e1 instanceof HTMLElement); // true
console.log(e1 instanceof Element); // true
console.log(e1 instanceof Node); // true
console.log(e1 instanceof EventTarget); // true
console.log(e1 instanceof Object); // true
Document.prototype.getElementById()
document는 생성자로 초기화시킨 객체 = "인스턴스" 이다.
document.getElementById("header4") 에서
document는 DOM Tree이다.
header4 는 <h1 id="header4" class"g2">제목2</h1> 이다.
리턴 값은 HTMLHeadingElement의 인스턴스를 리턴한다.
<h1> 태그는 HTMLHeadingElement() 로 초기화 시킨다.
<a> 태그는 HTMLAnchorElement() 로 초기화 시킨다.
HTMLHeadingElement() 생성자 체인과 객체의 관계
document.getElementById("header4") 에 의해 생성된 e1 객체는
Object() ~ HTMLHeadingElement() 의 각 모든 prototype를 call 할 수 있다.
e1 객체 안에
Object() 생성자가 프로퍼티를 추가한다.
EventTarget() 생성자가 프로퍼티를 추가한다.
Node() 생성자가 프로퍼티를 추가한다.
Element() 생성자가 프로퍼티를 추가한다.
HTMLElement() 생성자가 프로퍼티를 추가한다.
HTMLHeadingElement() 생성자가 프로퍼티를 추가한다.
EventTarget() 의 prototype 에 addEventListener() 가 있다.
Node() 의 prototype 에 appendChild() 가 있다. 프로퍼티 추가로 textContent 가 있다.
Element() 의 prototype에 querySelector(), setAttribute() 가 있다. 프로퍼티 추가로 innerHTML 이 있다.
HTMLElement() 의 prototype에 click(), blur() 가 있다. 프로퍼티 추가로 innerText, style 이 있다.
DOM API - 태그이름으로 태그 찾기
getElementByTagName 사용시
for ... in 문법 사용하면 프로퍼티까지 가져오므로 사용하지 말라.
for ... of 문법은 사용 가능하다.
<h1 id="header1" class="g1">제목1</h1>
<h2 id="header2" class="g1">제목1.1</h2>
<h2 id="header3" class="g1">제목1.2</h2>
<h1 id="header4" class="g2">제목2</h1>
<h2 id="header5" class="g2">제목2.1</h2>
<h2 id="header6" class="g2">제목2.2</h2>
<script>
"use strict"
// Document.prototype.getElementsByTagName("태그이름")
// => HTMLCollection 객체 리턴
// => HTMLCollection은 배열이 아니다!
//
var el = document.getElementsByTagName("h2");
//var e1 = $("h2");
console.log(el.constructor.name);
// HTMLCollection 객체는 배열은 아니지만,
// 배열처럼 length 프로퍼티가 있고,
// 인덱스 번호를 이용하여 찾은 태그들을 꺼낼 수 있다.
// => 그래서 반복문을 사용할 수 있다.
for (var i = 0; i < el.length; i++) {
console.log(i, el[i].innerHTML);
}
console.log("--------------------------");
// 그러나 for...in 문법을 사용하는 것은 조심해야 한다.
// for...in 에서는 배열이 아니고 일반 객체인 경우
// 프로퍼티 개수 만큼 반복한다.
// 그래서 프로퍼티 이름이 인덱스가 아닌 프로퍼티까지 반복하는 문제가 있다.
// 즉 HTMLCollection에 대해 다음과 같이 반복문을 사용하지 말라!
for (var i in el) { //el은 객체이기 때문에 i 변수에는 프로퍼티 이름이 저장된다.
//console.log(i, el[i]);
console.log(i, el[i].innerHTML);
}
console.log("--------------------------");
// HTMLCollection은 iterable 규칙을 구현하였기 때문에
// for...of 반복문을 사용할 수 있다.
// => for (var 변수 of 배열 또는 iterable 구현체) {...}
for (var e of el) {
console.log(e.innerHTML);
}
DOM API - 분류명(class)으로 태그 찾기
getElementsByClassName 으로 태그 찾으면 HTMLCollection을 리턴한다. 이는 배열이 아니다.
<h1 id="header1" class="g1">제목1</h1>
<h2 id="header2" class="g1">제목1.1</h2>
<h2 id="header3" class="g1 g3">제목1.2</h2>
<h1 id="header4" class="g2">제목2</h1>
<h2 id="header5" class="g2 g3">제목2.1</h2>
<h2 id="header6" class="g2 g3">제목2.2</h2>
<script>
"use strict"
// Document.prototype.getElementsByClassName("분류명")
// => HTMLCollection 객체 리턴
// => HTMLCollection은 배열이 아니다!
// => 찾지 못하더라도 HTMLCollection 객체를 리턴한다.
//
var el = document.getElementsByClassName("g3");
//var e1 = $(".g3");
console.log(el);
for (var e of el) {
console.log(e.innerHTML);
}
DOM API - CSS selector 문법으로 태그 찾기
querySelector("CSS selector 문법")
=> Element 객체 리턴
=> 만약 여러 개를 찾았다 할 지라도 그 중 첫 번째 것만 리턴한다.
// 1) 아이디로 찾기
var e = document.querySelector("#header3"); // $("#header3")
console.log(e);
console.log("---------------------");
// 2) 태그 이름으로 찾기
// => 조건에 해당하는 태그가 여러 개일지라도 그 중 첫 번째 것만 리터한다.
e = document.querySelector("h2"); // $("h2")
console.log(e);
console.log("---------------------");
//3) 분류명으로 찾기
//=> 조건에 해당하는 태그가 여러 개일지라도 그 중 첫 번째 것만 리터한다.
e = document.querySelector(".g2"); // $(".g2")
console.log(e);
console.log("---------------------");
//4) CSS selector 문법을 사용하기 때문에 복잡한 조건을 기술할 수 있다.
//=> 조건에 해당하는 태그가 여러 개일지라도 그 중 첫 번째 것만 리터한다.
e = document.querySelector(".g2.g3"); // $(".g2.g3")
console.log(e);
console.log("---------------------");
//5) 조건에 해당하는 태그를 찾지 못했다면?
// => 리턴 값은 null이다.
e = document.querySelector(".g2.g3.g4"); // $(".g2.g3.g4")
console.log(e);
DOM API - CSS selector 문법으로 태그 찾기 II
querySelectorAll("CSS selector 문법")
=> NodeList 객체 리턴
// 1) 아이디로 찾기
var list = document.querySelectorAll("#header3");
console.log("1) for...of ---------------------");
for (var e of list) {
console.log(e);
}
// NodeList는 배열이 아니다. 따라서 다음 반복문을 사용하면 필요없는 프로퍼티까지 반복하게 된다.
console.log("1) for...in ---------------------");
for (var i in list) {
console.log(list[i]);
}
// NodeList가 배열이 아니지만, 배열처럼 length 라는 변수가 있고,
// 인덱스를 통해 항목을 꺼낼 수 있다. 따라서 다음과 같이 반복문을 사용할 수 있다.
console.log("1) for(;;) ---------------------");
for (var i = 0; i < list.length; i++) {
console.log(list[i]);
}
// 2) 태그 이름으로 찾기
list = document.querySelectorAll("h2");
console.log("2) ---------------------");
for (var e of list) {
console.log(e);
}
//3) 분류명으로 찾기
list = document.querySelectorAll(".g2");
console.log("3) ---------------------");
for (var e of list) {
console.log(e);
}
//4) CSS selector 문법을 사용하기 때문에 복잡한 조건을 기술할 수 있다.
list = document.querySelectorAll(".g2.g3");
console.log("4) ---------------------");
for (var e of list) {
console.log(e);
}
//5) 조건에 해당하는 태그를 찾을 수 없다면?
// => 빈 NodeList 객체이다.
list = document.querySelectorAll(".g2.g3.g1");
console.log("5) ---------------------");
for (var e of list) {
console.log(e);
}
DOM API - HTMLCollection과 NodeList
HTMLCollection은 삭제 후 상태를 실시간 반영하고 싶을때 사용한다.
NodeList는 삭제 해도 리턴받은 상태를 그대로 유지하고 싶을때 사용한다.
현재 상태를 알고 싶으면 다시 변수에 집어넣어야 한다.
<li>테스트1</li>
<li>테스트2</li>
<li>테스트3</li>
<li>테스트4</li>
<li>테스트5</li>
<li>테스트6</li>
</ul>
<button id="btn1" type="button">삭제</button>
<script>
"use strict"
var list1 = document.getElementsByTagName("li");
var list2 = document.querySelectorAll("li");
console.log(list1);
console.log(list2);
document.querySelector("#btn1").onclick = function() {
var e = document.querySelector("li:first-child");
e.parentElement.removeChild(e);
console.log(list1); // HTMLCollection 은 현재 태그 상태를 반영한다.
console.log(list2); // NodeList는 리턴 받은 값을 그대로 유지한다.
console.log("-------------------------");
};
DOM API - 태그의 콘텐트 알아내기
innerHTML : 자식 태그를 살려서 꺼낸다.
textContent : 태그 없이 순수 text만 꺼낸다.
innerText : 태그 없이 순수 text만 꺼낸다.
<section>
<article>
<h1 id="header1">자바스크립트</h1>
<p>자바스크립트는 <b>프론트-엔드</b>를 개발할 때 사용하는 프로그래밍 언어입니다.</p>
</article>
<article>
<h1 id="header2">자바</h1>
<p>자바는 <b>백-엔드</b>에서 사용하는 프로그래밍 언어입니다.
<i>스프링 프레임워크</i>는 자바 백-엔드 개발 프레임워크입니다.
</p>
</article>
</section>
<script>
"use strict"
// Element.innerHTML : DOMString
// => Element() 생성자가 추가한 프로퍼티이다.
// => 태그의 콘텐트를 HTML 코드 그대로 리턴한다.
//
var e = document.querySelector("article:first-child > p");
console.log(e)
console.log(e.innerHTML)
console.log("----------------------")
// Node.textContent
// => Node() 생성자가 추가한 프로퍼티이다.
// => 태그의 콘텐트에서 HTML 코드를 제거한 후 텍스트만 리턴한다.
console.log(e.textContent)
console.log("----------------------")
// HTMLElement.innerText
// => Node() 생성자가 추가한 프로퍼티이다.
// => 태그의 콘텐트에서 HTML 코드를 제거한 후 텍스트만 리턴한다.
console.log(e.innerText)
console.log("----------------------")
DOM API - 태그의 콘텐트 설정하기 I
innerHTML : HTML 태그가 그대로 렌더링한다.
textContent : HTML 태그도 일반 텍스트로 취급한다.
innerText : HTML 태그도 일반 텍스트로 취급한다.
HTMLElement 는 HTML 태그에 대해서 다루는 생성자다.
innerHTML, innerText 를 사용하라.
<section>
<article>
<h1 id="header1">자바스크립트</h1>
<p>자바스크립트는 <b>프론트-엔드</b>를 개발할 때 사용하는 프로그래밍 언어입니다.</p>
</article>
<article>
<h1 id="header2">자바</h1>
<p>자바는 <b>백-엔드</b>에서 사용하는 프로그래밍 언어입니다.
<i>스프링 프레임워크</i>는 자바 백-엔드 개발 프레임워크입니다.
</p>
</article>
<article>
<h1 id="header3">SQL</h1>
<p>SQL은 <b>DBMS</b>에서 사용하는 데이터 질의문 작성 언어입니다.
</p>
</article>
</section>
<button id="btn1">바꿔라!</button>
<script>
"use strict"
document.querySelector('#btn1').onclick = function () {
// Element.innerHTML : DOMString
// => Element() 생성자가 추가한 프로퍼티이다.
// => HTML 코드로 태그의 콘텐트를 설정할 수 있다.
// => HTML 태그가 그대로 렌더링 된다.
//
var e = document.querySelector("article:first-child > p");
e.innerHTML = "오호라 <b>비트캠프</b>입니다.<br> 반갑습니다.";
// Node.textContent
// => Node() 생성자가 추가한 프로퍼티이다.
// => 텍스트를 설정할 때 사용한다. 텍스트 안에 HTML 코드는 그냥 일반 텍스트로 취급한다.
// 즉 텍스트 안에 있는 HTML 코드는 웹브라우저가 인식하지 않는다.
e = document.querySelector("article:nth-child(2) > p");
e.textContent = "우헤헤 <b>비트캠프</b>입니다.<br> 반갑습니다.";
// HTMLElement.innerText
// => HTMLElement() 생성자가 추가한 프로퍼티이다.
// => 텍스트를 설정할 때 사용한다. 텍스트 안에 HTML 코드는 그냥 일반 텍스트로 취급한다.
// 즉 텍스트 안에 있는 HTML 코드는 웹브라우저가 인식하지 않는다.
e = document.querySelector("article:last-child > p");
e.innerText = "헐 <b>비트캠프</b>입니다.<br> 반갑습니다.";
};
DOM API - 태그의 속성(attribute) 변경하기
<a href="#"> 의 href를 선택하는 방법이다.
<section>
<article>
<h1 id="header1">자바스크립트</h1>
<p>자바스크립트는 <b>프론트-엔드</b>를 개발할 때 사용하는 프로그래밍 언어입니다.</p>
</article>
<article>
<h1 id="header2">자바</h1>
<p>
자바는 <b>백-엔드</b>에서 사용하는 프로그래밍 언어입니다.
<a href='http://www.spring.io'>스프링 프레임워크</a>는 자바 백-엔드 개발 프레임워크입니다.
</p>
</article>
</section>
<button id="btn1">바꿔라!</button>
<script>
"use strict"
// 태그의 속성 바꾸기
//
var e = document.querySelector("article:nth-child(2) a");
console.log(e.href)
console.log(e.getAttribute('href'))
document.querySelector('#btn1').onclick = function () {
// 1) 방법1
// => 원래 태그에 있던 속성 값을 바꿀 때!
// 태그객체.속성명 = "값"
e.href = "http://www.daum.net";
// 2) 방법2
// => 원래 태그에 있던 속성 값을 바꿀 때
// 태그객체.setAttribute("속성명", "값")
// => 이 메서드를 사용하면 개발자가 임의로 추가한 프로퍼티 값도 바꿀 수 있다.
// 즉 원래 태그 객체에 없던 프로퍼티 값도 설정할 수 있다.
// e.setAttribute("href", "http://www.google.com");
};
DOM API - 태그에 속성(attribute)을 추가하기
태그에 임의의 속성 추가하는 방법
<section>
<article>
<h1 id="header1">자바스크립트</h1>
<p>자바스크립트는 <b>프론트-엔드</b>를 개발할 때 사용하는 프로그래밍 언어입니다.</p>
</article>
<article>
<h1 id="header2">자바</h1>
<p>자바는 <b>백-엔드</b>에서 사용하는 프로그래밍 언어입니다.
<a href='http://www.spring.io'>스프링 프레임워크</a>는 자바 백-엔드 개발 프레임워크입니다.
</p>
</article>
</section>
<script>
"use strict"
// 태그에 임의의 속성을 추가할 수 있다.
//
var e = document.querySelector("article:nth-child(2) a");
// 1) 방법1
// => 사용자(개발자)가 태그 객체에 없던 임의의 속성(태그의 공식적인 속성이 아닌 경우)을 추가할 때는
// 기존의 속성 이름과 같은 이름으로 덮어쓰지 않도록 하기 위해
// HTML5에서는 "data-xxxx" 형식으로 이름을 짓도록 권고하고 있다.
// => '-' 문자는 일반 프로퍼티 명으로 사용할 수 없다.
// 따라서 "객체.프로퍼티명" 이 아닌 "객체['프로퍼티명']" 문법을 사용해야 한다.
//
//e.data-no = 200; // 프로퍼티 이름 중간에 - 가 있는 경우 일반적인 방식으로 사용할 수 없다.
e["data-no"] = 200;
console.log(e["data-no"]);
console.log(e.getAttribute("data-no")); // 객체에 직접 저장한 프로퍼티는 꺼낼 수 없다.
// 위의 방식으로 태그에 임의의 속성(태그의 공식 속성이 아닌 경우)을 추가하게 되면 값을 넣고 꺼낼 수는 있으나
// 웹브라우저의 개발 도구에서 디버깅할 때 추가된 속성을 볼 수 없다.
// 디버깅을 쉽게 하려면 다음 방식을 사용하라!
// 2) 방법2
e.setAttribute("data-no2", 300);
console.log(e.getAttribute("data-no2"));
console.log(e["data-no2"]); // setAttribute()로 추가한 속성은 꺼낼 수 없다.
DOM API - 태그 추가하기
appendChild로 태그 추가하는 방법
<section>
<article>
<h1 id="header1">자바스크립트</h1>
<p>자바스크립트는 <b>프론트-엔드</b>를 개발할 때 사용하는 프로그래밍 언어입니다.</p>
</article>
<article>
<h1 id="header2">자바</h1>
<p>자바는 <b>백-엔드</b>에서 사용하는 프로그래밍 언어입니다.
<a href='http://www.spring.io'>스프링 프레임워크</a>는 자바 백-엔드 개발 프레임워크입니다.
</p>
</article>
</section>
<button id="btn1">추가하라!</button>
<script>
"use strict"
// 태그를 만들고 추가하는 방법
//
var section = document.querySelector("section");
// 1) 태그 만들기
// => Document.prototype.createElement("태그명")를 사용하여 태그 객체를 만든다.
//
var article = document.createElement("article"); // <article></article>
var h1 = document.createElement("h1"); // <h1></h1>
var text = document.createTextNode("제목입니다."); // 제목입니다.
var p = document.createElement("p"); // <p></p>
var text2 = document.createTextNode("내용입니다."); // 내용입니다.
// 2) 태그에 자식 노드를 붙이기
// => appendChild(자식노드)를 사용하여 자식 태그나 노드를 붙인다.
// appendChild()는 자식노드(태그)를 맨 뒤에 붙인다.
//
// Node의 함수를 사용해서 콘텐트를 설정할 수 있다.
h1.appendChild(text); // <h1>제목입니다.</h1>
// h1.innerHTML = "제목입니다."; // innerHTML에 직접 값을 넣을 수 도 있다.
p.appendChild(text2); // <p>내용입니다.</p>
// p.innerHTML = "내용입니다.";
article.appendChild(h1); // <article><h1>제목입니다.</h1></article>
article.appendChild(p); // <article><h1>제목입니다.</h1><p>내용입니다.</p></article>
document.querySelector('#btn1').onclick = function () {
// 새로 만든 article 태그를 section 태그의 막내 자식태그로 붙인다.
section.appendChild(article);
// <section>
// <article>...</article>
// <article>...</article>
// <article><h1>제목입니다.</h1><p>내용입니다.</p></article>
// </section>
}
DOM API - 태그 추가하기 II
text에 태그를 입력해서 innerHTML로 태그 추가하는 방법
<section>
<article>
<h1 id="header1">자바스크립트</h1>
<p>자바스크립트는 <b>프론트-엔드</b>를 개발할 때 사용하는 프로그래밍 언어입니다.</p>
</article>
<article>
<h1 id="header2">자바</h1>
<p>자바는 <b>백-엔드</b>에서 사용하는 프로그래밍 언어입니다.
<a href='http://www.spring.io'>스프링 프레임워크</a>는 자바 백-엔드 개발 프레임워크입니다.
</p>
</article>
</section>
<button id="btn1">추가하라!</button>
<script>
"use strict"
// 태그를 만들고 추가하는 방법 II
//
var section = document.querySelector("section");
document.querySelector('#btn1').onclick = function () {
// 태그 객체를 만들지 않고 텍스트를 사용하여 자식 태그를 추가할 수 있다.
var originContent = section.innerHTML;
console.log(originContent);
section.innerHTML = originContent +
"<article><h1>제목이래요!</h1><p>내용이지요!</p></article>";
};
DOM API - 태그 삭제하기
removeChild 로 삭제하는 방법
<section>
<article>
<h1 id="header1">자바스크립트</h1>
<p>자바스크립트는 <b>프론트-엔드</b>를 개발할 때 사용하는 프로그래밍 언어입니다.</p>
</article>
<article>
<h1 id="header2">자바</h1>
<p>자바는 <b>백-엔드</b>에서 사용하는 프로그래밍 언어입니다.
<a href='http://www.spring.io'>스프링 프레임워크</a>는 자바 백-엔드 개발 프레임워크입니다.
</p>
</article>
</section>
<button id="btn1">삭제하라!</button>
<script>
"use strict"
// 태그를 삭제하기
//
document.querySelector('#btn1').onclick = function () {
// 방법1) 부모 태그를 알고 있다면 removeChild()를 이용하여 삭제한다.
// => 삭제할 태그를 찾는다.
var e = document.querySelector("article:first-child");
// => 부모 태그를 찾는다.
var parent = document.querySelector("section");
// => 부모 태그에서 자식 태그를 제거한다.
parent.removeChild(e);
};
DOM API - 태그 삭제하기 II
삭제하려는 태그에서 parentElement 사용해서 삭제하는 방법
<section>
<article>
<h1 id="header1">자바스크립트</h1>
<p>자바스크립트는 <b>프론트-엔드</b>를 개발할 때 사용하는 프로그래밍 언어입니다.</p>
</article>
<article>
<h1 id="header2">자바</h1>
<p>자바는 <b>백-엔드</b>에서 사용하는 프로그래밍 언어입니다.
<a href='http://www.spring.io'>스프링 프레임워크</a>는 자바 백-엔드 개발 프레임워크입니다.
</p>
</article>
</section>
<button id="btn1">삭제하라</button>
<script>
"use strict"
// 태그를 삭제하기 II
//
document.querySelector('#btn1').onclick = function () {
// 방법2) 부모 태그를 모른다면 찾은 태그에서 부모 태그를 알아낸다.
// => 삭제할 태그를 찾는다.
var e = document.querySelector("article:first-child");
// => 부모 태그를 알아낸다.
// => Node.parentElement 또는 Node.parentNode를 사용한다.
var parent = e.parentElement;
// => 부모 태그에서 자식 태그를 제거한다.
parent.removeChild(e);
};
DOM API - appendChild() 응용
롤링 이미지 구현 : 첫번째 자식을 마지막에 추가하면 돌아가는 것 처럼 보인다.
<section>
<img src="../img01.jpeg" style="height:200px;">
<img src="../img02.jpeg" style="height:200px;">
<img src="../img03.jpeg" style="height:200px;">
<img src="../img04.jpeg" style="height:200px;">
<img src="../img05.jpeg" style="height:200px;">
<img src="../img06.jpeg" style="height:200px;">
</section>
<script>
"use strict"
// appendChild()를 이용하여 이미지 회전하기
//
// img 태그의 부모 태그를 찾는다.
var parent = document.querySelector("section");
// 2초마다 부모 태그의 첫 번째 자식을 막내 자식으로 보낸다.
window.setInterval(() => {
// 첫 번째 이미지를 찾는다.
var img = document.querySelector("section > img:first-child");
// 찾은 이미지를 부모의 막내 자식으로 추가한다.
// => 이미 존재하는 태그를 추가하면 또 추가되는 것이 아니라
// 기존 위치에서 맨 끝으로 이동하게 된다.
parent.appendChild(img);
}, 1000);
조언
*
과제
15 퍼즐 만들기
내용:
- 1에서 15까지 숫자를 4x4 로 정렬하는 퍼즐 게임이다.
- "3.html_css_javascript2.pdf"에 제시된 화면을 만족해야 한다.
과제 제출 조건:
- zip 압축파일로 제출할 것.
- 압축 파일을 풀었을 때 디렉토리 구조는 다음과 같아야 한다.
- index.html
- css/*.css
- js/*.js
- 팀원 각자가 팀 프로젝트 파일을 제출할 것
- 제출 내용에 다음과 같이 팀명 및 팀원을 명시할 것
예) 1팀:양창덕,조준호,박경한
제출 마감일:
- 2022-12.15(목요일) 09:00
'네이버클라우드 AIaaS 개발자 양성과정 1기 > Javascript' 카테고리의 다른 글
[비트캠프] 29일차(6주차4일) - AJAX 개요 (0) | 2022.12.15 |
---|---|
[비트캠프] 28일차(6주차3일) - Javascript(이벤트: 등록, 정보 다루기, 전파, 기본 동작 중지) (0) | 2022.12.14 |
[비트캠프] 26일차(6주차1일) - Javascript(객체, 프로퍼티, 생성자) (0) | 2022.12.12 |
[비트캠프] 25일차(5주차5일) - Javascript(함수, 비동기, 주요함수, JSON) (0) | 2022.12.09 |
[비트캠프] 24일차(5주차4일) - Javascript(함수: 정의, closure, arrow function) (0) | 2022.12.08 |