본문 바로가기
HTML, CSS, JS

2022-10-04 함수의 호이스팅, 표현식, DOM

by HTT 2022. 10. 5.
호이스팅

 

: 함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.

- 자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언한다.
  자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑는다.
  함수 안에 존재하는 변수/함수선언에 대한 정보를 기억하고 있다가 실행시킨다.
  유효 범위: 함수 블록 {} 안에서 유효
- 즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다.
실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것이다.
실제 메모리에서는 변화가 없다.
https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html

 

 

표현식
window.onload = function() {        //익명함수
		document.getElementById("btndomtest").onclick = domTest;
		}
		function domTest() {   ~   }

 

 

 

DOM

 

- 표준화를 통해 문서 하나하나를 제어하고 싶을 때 사용

 

- 접근방법 : 메소와 속성을 알아야 함

 

- nodeName : 노드(엘리먼트)의 이름
- FirstChild : 첫 번째 자식노드 (노드객체)
- LastChild : 마지막 자식노드 (노드객체)
- childNodes : 모든 자식노드들
                       하나의 엘리먼트가 갖고 있는 모든 자식노드를 NodeList의 형태로 반환

                       (html문서에 저장된 순서대로 배열에 저장)

 

* p, div... 와 같은 태그는  element node라고 함

* h1, h2... 와 같은 태그는 text node 라고 함

* console창에서 공백은 #TEST로 표시됨

 

 

 

<basic>

<  DOM객체를 접근하는 방법  >

	<script type="text/javascript">
		// DOM객체가 생성되고 페이지가 로딩되면 익명의 함수를 실행
		// 1. btndomtest라는 id로 정의된 객체를 찾아서 클리이벤트에 반응할 수 있도록 함수를 연결
		// (domTest라는 함수를 클릭이벤트가 발생하면 실행될 수 있도록 연결)
		window.onload = function() {
			document.getElementById("btndomtest").onclick = domTest;
		}
		function domTest() {
			//alert("domTest");
			// 모든 div태그를 찾아온다. - 모든 div를 NodeList의 형태의 반환(배열로 관리)
			var obj2 = document.getElementsByTagName("div");
			//alert(obj2);
			// 반환된 NodeList(배열)에 저장된 노드의 갯수 - 배열의 요소를 갯수로 반환
			alert("<div>노드의 갯수=>"+obj2.length);
			// 배열로 관리되기 때문에 for문으로 접근
			for(var i=0; i<obj2.length; i++){
				console.log(obj2[i]);
				console.log("div태그의 id속성:"+obj2[i].getAttribute("id"));
				//id가 domtestbtn인 객체를 확인하고 싶을 떄
				if(obj2[i].getAttribute("id") == "domtestbtn"){
					console.log("폼객체")
				}
				console.log("노드의 첫 번째 자식노드=>"+obj2[i].firstChild.nodeName);
				/* var childobj = obj2[i].firstChild;
				childobj.nodeName */
				console.log("노드의 마지막 자식노드=>"+obj2[i].lastChild.nodeName);
				
				//모든 노드들의 자식노드들 구하기
				var mynodelist = obj2[i].childNodes;
				console.log("각 div노드의 자식노드의 갯수=>"+mynodelist.length);
			}
		}
	</script>
	<body>
		<div id="main">
			<h1 id="myhead">안녕하세요 DOM에 관한 작업을 수행 중입니다.</h1>
			<div id="mycontent1"><img src="../images/yc05.jpg" name="myimg" id="myimagId"
					alt="이미지파일" /><h3>이미지파일</h3></div>
			<div id="mycontent2">DOM의 구조를 볼까~~</div>
			<div id="domtestbtn">
				<form id="myformId" name="myform">		
					<input type="button" value="dom구조확인하기"
						 name="btn" id="btndomtest" />
					<input type="button" value="노드삽입하기"
						 name="btn" id="btninsert" />
					<input type="button" value="이미지노드삽입하기"
						 name="btn" id="imginsert" />					 
					<input type="button" value="특정노드전에 삽입하기"
						 name="btn" id="btninsertbefore" />
					<input type="button" value="특정노드삭제하기"
						 name="btn" id="btndelete" />
				</form>
			</div>
		</div>
	</body>
</html>

*  배열로 관리되기 때문에 for문으로 접근!

obj2[i]   <- 이런식으로 [ ] 붙이기

 

 

- 자식노드 가져오기

window.onload = function() {
	document.getElementById("accessdom").onclick = function() {
    
			// 1. 어디에서 가져올건지
			var myformnode = document.getElementById("myform");
            
			// 2. 어떤 걸 가져올건지
            
			var mychildlist = myformnode.childNodes;
			console.log("자식노드의 갯수 : " + mychildlist.length);
			// 3. mychildlist의 길이만큼 for문 돌려서 자식노드들의 타입 출력하기
            
			for (i=0; i<mychildlist.length; i++){
			console.log(mychildlist[i].nodeName+":");
			}		
	}
}

 

 

1. 텍스트노드 추가하기

 

1. 추가하고 싶은 노드 생성하기

2. 1번에서 만든 텍스트 노드가 추가될 부모노드 구하기

3. 2번에서 구한 부모노드에 1번에서 만든 텍스트노드 추가하기

<body>
	<script type="text/javascript">
		window.onload = function() {
			document.getElementById("btninsert").onclick = function() {
				
				// 1. 추가하고 싶은 노드 생성하기
			var newTextNode = document.createTextNode("삽입될 텍스트~~~~~~~")
				// 2. 1번에서 만든 텍스트 노드가 추가될 부모노드 구하기
			var parentNode = document.getElementById("domtestbtn");
				// 3. 2번에서 구한 부모노드에 1번에서 만든 텍스트노드 추가하기
			parentNode.appendChild(newTextNode);
			}
		}
	</script>
</body>

* 어디에 추가할지, 무엇을 추가할지, 부모노드 구하기, 출력하기

 

 

2. 태그노드 추가하기

 

1. 추가하고 싶은 노드 생성하기

2. 속성을 설정

3. 부모노드 구하기

4. 부모노드에 추가하기

<head>
	<script type="text/javascript">
		window.onload = function() {
			document.getElementById("imginsert").onclick = function() {
            
			// 1. 삽입될 노드 생성하기
			var newimgnode = document.createElement("img");   //p, div ...
			// 2. 속성을 설정
			newimgnode.setAttribute("src","/clientweb/images/yc03.jpg");
			newimgnode.setAttribute("style", "border: solid blue 5px; width:200px;");
			// 3. 부모노드 구하기
			var parentNode = document.getElementById("domtestbtn");
			// 4. 부모노드에 추가하기
			parentNode.appendChild(newimgnode);
			}
		}
	</script>
</head>

* 텍스트노드에서 속성추가하기만 늘어남. setAttribute 사용하기.

 

 

3. 특정노드 삭제하기

 

1. 삭제하고 싶은 부모노드 구하기

2. 삭제할 노드를 구하기

3. 노드 삭제하기

<head>
	<script type="text/javascript">
		window.onload = function() {
			document.getElementById("btndelete").onclick = function() {
            
			//1. 삭제하고 싶은 부모노드 구하기
			var parentNode = document.getElementById("myformId");
            
			//2. 삭제할 노드를 구하기
			//var delNode = document.getElementById("imginsert");
			var delNode = parentNode.firstChild;
            
			//3. 노드 삭제하기
			var delNode = parentNode.firstElementChild;
			parentNode.removeChild(delNode);
			}
		}
	</script>
</head>

	<body>
		<div id="main">
			<h1 id="myhead">안녕하세요 DOM에 관한 작업을 수행 중입니다.</h1>
			<div id="mycontent1"><img src="../images/m_garden07.jpg" name="myimg" id="myimagId"
					alt="이미지파일" /><h3>이미지파일</h3></div>
			<div id="mycontent2">DOM의 구조를 볼까~~</div>
			<div id="domtestbtn">
				<form id="myformId" name="myform">		
					<input type="button" value="dom구조확인하기"
						 name="btn" id="btndomtest" />
					<input type="button" value="노드삽입하기"
						 name="btn" id="btninsert" />
					<input type="button" value="이미지노드삽입하기"
						 name="btn" id="imginsert" />
						 
					<input type="button" value="특정노드전에 삽입하기"
						 name="btn" id="btninsertbefore" />
					<input type="button" value="특정노드삭제하기"
						 name="btn" id="btndelete" />
				</form>
				
			</div>
		</div>
	</body>

* 삭제할 노드가 무엇이냐에 따라 부모노드가 달라짐(생각하면서 부모노드 정하기)

=> <div id="domtestbtn">의 자식노드들을 전부 삭제하고 싶다면 얘가 부모노드

<input>노드 중 특정한 노드만 삭제하고 싶다면 <form>을 부모노드로 잡기!! 유동적으로.

 

 

<과제>

(1) <p></p>태그 생성

(2) text 추가하기, 속성주기

(3) 부모노드 구하기

구현목표

P추가-newP생성, P삭제- newP삭제
<div id="root">의 자식노드들 모두 삭제(root 제외)

<!DOCTYPE html>
<html>
	<head>
	<meta charset="UTF-8">
	<title>Insert title here</title>    <!-- 텍스트노드-> p노드-> root노드 -->
	<script type="text/javascript">
		window.onload = function() {
			document.getElementById("plus").onclick = function insertP() {
				var myplus = document.createElement("p");
 				var newTextNode = document.createTextNode("newP");
 				var boomoNode = document.getElementById("root");
 				myplus.appendChild(newTextNode);
                
				myplus.setAttribute("style", "background: pink");	
				var boomoNode = document.getElementById("root");
				boomoNode.appendChild(myplus);
			}
				document.getElementById("Delete").onclick = function deleteP() {
					var mydelete = document.getElementById("root");
					var delNode = mydelete.lastElementChild;
					mydelete.removeChild(delNode);
				}
	  			document.getElementById("alldelete").onclick = function deleteDivAndP() {
					let element = document.getElementById("root");
					while (element.firstChild) {
						element.removeChild(element.firstChild);
					}
				}
		}
		
	  *** 강사님 풀이 ***
 		function insertP(){
			// 1. 사용할 노드생성
			var pNode = document.createElement("p");
			pNode.setAttribute("style", "background: pink");
			var textNode = document.createTextNode("newP");
			// 2. 1번에서 작업한 노드를 추가할 부모노드 구하기
			var boomo = document.getElementById("root");
			// 3. 노드 추가하기
			pNode.appendChild(textNode);
			boomo.appendChild(pNode);
		}
	  
		function deleteP()
		
		function deleteDivAndP(){
			var parentNode = document.getElementById("root");
			var nodeList = parentNode.childNodes;
			var size = nodeList.length;
				for(i=0; i<size; i++){
					parentNode.removeChild(parentNode.lastChild);
				}
					
			// 또는
			// hasChildNodes()는 해당노드에 child노드가 있으면 true, 아니면 false를 리턴
			// parentNode에 child노드가 존재한다면 while문을 실행하여 반복적으로 노드를삭제하겠다는 의미
			while(parentNode.hasChildNodes()){
				parentNode.removeChild(parentNode.lastChild);
			}
		}
		
	</script>
	</head>
	<body>
		<div id="layer"></div>
	
		<hr>
	
		<div id="root">
			<p style="background: gray;">line01</p>
			<p style="background: skyblue">line02</p>
			<p style="background: green;">line03</p>
			<p style="background: red;">line04</p>
			<p></p> 
		</div>
	
		<hr>
		<button onclick="insertP()" id="plus">P태그추가하기</button>
		<button onclick="deleteP()" id="Delete">P태그삭제하기</button>
		<button onclick="deleteDivAndP()" id="alldelete">div안의 모든 p태그 삭제하기</button>
		<button onclick="innerHTML_test()">innerHTML</button>
	</body>
</html>
텍스트, 속성 추가하고 출력할 때 총 두 번 써줘야함(+ , 금지......)
(처음에 한 번만 했다가 텍스트만 추가되었다 ......)

myplus.appendChild(newTextNode);
boomoNode.appendChild(myplus);

 

 

** 자식노드들 삭제하는 부분에서 왜 자꾸 오류가 나나 했더니 이런식으로 해야했음

function deleteDivAndP(){
		var parentNode = document.getElementById("root");
		var nodeList = parentNode.childNodes;
		var size = nodeList.length;
			for(i=0; i<size; i++){
				parentNode.removeChild(parentNode.lastChild);
		}

 

** 혹은 while문을 사용해 조건을 만족하는 조건이 항상 참일 때마다 remove 실행

function deleteDivAndP(){
	var parentNode = document.getElementById("root");
	var nodeList = parentNode.childNodes;
   
		while(parentNode.hasChildNodes()){     
			parentNode.removeChild(parentNode.lastChild);
		}
}

* hasChildNodes()는 해당노드에 child노드가 있으면 true, 아니면 false를 리턴
* parentNode에 child노드가 존재한다면 while문을 실행하여 반복적으로 노드를삭제하겠다는 의미

 

 

[과제를 하면서 몰랐던 부분...]

text에는 속성을 줄 수 없다................. 속성은 p태그에 주기...

newTextNode.setAttribute("style", "background: pink");

댓글