ShortCut
줄 이동 : Opt + Shft + 화살표
줄 복사 : Cmd + D
Node.js(without Browser ) = Javascript
let vs var
- 변수의 scope 차이
1. Hosting
- 코드 실행 전 변수선언/함수선언 을 해당 스코프의 최상단으로 끌어올리는 것이 아님
- 끌어 올려진 것 같은 현상을 말함
* js 엔진은 코드 실행 전 코드를 형상화하고 구분하는 과정(실행 context를 위한 과정)을 거침.
→ 즉 실행 전 실행 context를 위한 과정에서 모든 선언(var, let, const, function, class)을 스코프에 등록함
- 코드 실행 전 이미 변수선언/함수선언 이 저장되어 있기에 선언문보다 참조/호출이 먼저 나와도 오류 없이 동작함 (정확히는 var 키워드로 선언한 변수와 함수 선언문일 경우 오류 없이 동작. 이는 선언이 파일의 맨 위로 끌어올려진 것처럼 보이게 함)
- *실행 context는 실행 가능한 코드가 실행되기 위해 필요한 환경을 의미. 실행되기 전 이러한 실행 context 과정(코드를 구분하는 과정)을 거침
1-1. 변수 Hoisting (var, let, const 키워드)
- var 키워드로 선언된 변수와는 달리 let 키워드로 선언된 변수를 선언문 이전에 참조하면 참조 에러 (Reference Error)가 발생 → 이는 let 키워드로 선언된 변수는 스코프의 시작에서 변수의 선언까지 *일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문.
!! 이 Hoisting이란 용어가 ‘선언이 먼저 메모리에 저장되었다’ 를 의미하기에, 즉 ‘선언이 끌어올려진다’는 의미라서 모든 선언은 Hoisting이 일어난다는 말은 참.
→ 선언문 이전에 참조해서 에러를 발생시킨다고 Hoisting이 일어나지 않은 것은 아니라는 것.
1-2. Ex 코드
let foo = 1;
{
console.log(foo);
let foo = 2;
}
1-3. 변수 생성 방법 및 Hoisting
- 선언 단계(Declaration phase)
- 변수를 실행 context의 변수 객체에 등록
- 이 변수 객체는 스코프가 참조하는 대상이 됨
- 초기화 단계(Initialization phase)
- 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보
- 이 단계에서 변수는 undefined로 초기화 됨
- 할당 단계(Assignment phase)
- undefined로 초기화 된 변수에 실제 값을 할당
2. 함수 & 람다식 표현 정리
2-1. 익명 함수 (Noname Function)
let f = function () {
console.log("fun2 함수");
};
f(); // "fun2 함수" 출력
// 변수에 담을 수 있는 근거 = JS는 1급객체라. => 매개 변수에 전달 가능
- function () { … } = 익명 함수.
- 이 함수는 변수 f 에 할당되어 f() 호출 시 함수 실행
2-2. 함수 표현식 (Function Expression)
함수 정의 및 그 값을 변수에 할당하는 방식.
Return 값이 있는 경우 이를 표현
let f1 = function () {
console.log("fun3 함수");
return 1; // return이 있으므로 표현식으로 간주됨
};
let result = f1(); // "fun3 함수" 출력, result는 1
2-3. 람다 표현식 (Arrow Function)
익명 함수 사용 시 간결하게 작성하기 위한 방식
let f2 = () => {
return 1;
};
let result2 = f2(); // result2는 1
축약 함수
let f3 = () => 3;
let result3 = f3(); // result3는 3
let f4 = () => { console.log(1); }; // 코드 처리가 많을 땐 이거로 처리
- { } 없이 return 생략, 바로 작성 시 해당 값 자동 return
let f = function () { // 익명 함수 (noname funtion)
console.log("fun2 함수");
}
f();
// 변수에 담을 수 있는 근거 = JS는 1급객체라. => 매개 변수에 전달 가능
let f1 = function () { // 표현식(expression) = return 되야함=람다식, 하지만 이 라인은 아님. -> 내부에서 실행만 됨
console.log("fun3 함수");
return 1; // expression으로 바뀌려면 이렇게
}
f1();
let f2 = () => {
return 1; // 람다표현식 / 람다식은 console로 처리.
}
f2();
let f3 = () => 3; // {} 없으면 $표현식 -> 자동 return 됨 => 람다 표현식 / 간단한 연산 처리 시 사용
let f4 = () => { console.log(1); }; // 람다식 / 코드 처리가 많을 땐 이거로
// 매개변수에 함수를 전달하기 위해 () => 1; 이거로 전달 가능 = 가독성 UP
3. Event with Ajax - DOM 제어
- addEventListener() 메소드를 통해 Event Handler 등록
<button id="myBtn">Click me</button>
<script>
const myBtn = document.getElementById("myBtn");
myBtn.addEventListener("click", function() {
alert("Hello World!");
});
</script>
→ HTML과 JS 코드를 분리해서 유지 보수 쉽게 가능.
addEventListener() 메소드는 Event 이름과 Event Handler 함수를 인자로 받음
3-1. Test(실습)
1. click : 요소 클릭시 발생
2. dbclick : 요소 더블 클릭 시 발생
3. mousedown : 요소에서 마우스 버튼이 눌릴 때 발생
4. mouseup : 요소에서 마우스 버튼이 떼어질 때 발생
5. mousemove : 요소에서 마우스가 움직일 때 발생
6. mouseover : 요소에 마우스 커서가 올라갈 때 발생
7. mouseout : 요소에서 마우스 커서가 벗어날 때 발생
8. keydown & keyup : 키보드에서 키를 누르거나 뗄 때 발생
9. submit : 폼 제출 시 발생
10. change : 요소의 값 변경 시 발생
11. load : 웹 페이지나 이미지 등이 로딩 시 발생
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="myBtn">Click me</button>
<input type="text" id="myIp">
<script> // ex) 더블 클릭으로 e 발생
const myBtn = document.getElementById("myBtn");
myBtn.addEventListener("click", function (e) {
console.log(e);
});
const myIp = document.getElementById("myIp");
myIp.addEventListener("change", function (e) {
console.log(e);
console.log(e.target.value);
});
</script>
</body>
</html>

3-2. DOM 숨기기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
border: 1px solid black;
padding: 10px;
}
</style>
</head>
<body>
<h1>숨기기</h1>
<button onclick="hideDisplay()">display로 숨기기</button>
<button onclick="hideVisible()">visible로 숨기기</button>
<div class="box">
<div class="box" id="innerBox1"> 내부박스1</div>
<div class="box" id="innerBox2"> 내부박스2 </div>
</div>
<script>
function hideDisplay() {
let el = document.querySelector("#innerBox1");
el.style.display = "none"; //
}
function hideVisible() {
let el = document.querySelector("#innerBox2");
el.style.visibility = "hidden"; // 영역이 남은채로 해당 부분이 사라짐
}
</script>
</body>
</html>
display = “none”;

visibility = “hidden”

3-3. DOM 나타내기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
border: 1px solid black;
padding: 10px;
}
#innerBox1 {
display: none;
}
#innerBox2 {
visibility: hidden;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<h1>나타내기</h1>
<button onclick="showByDisplay()">display로 나타내기</button>
<button onclick="showByVisible()">visible로 나타내기</button>
<div class="box" id="outerBox">
<div class="box" id="innerBox1"> 내부박스1
</div>
<div class="box" id="innerBox2">
내부박스2 </div>
</div>
<script>
function showByDisplay() {
// let el = document.querySelector("#innerBox1");
// el.style.display = "block"; // 전체 영역 차지
$("#innerBox1").css("display", "block");
}
function showByVisible() {
// let el = document.querySelector("#innerBox2");
// el.style.visibility = "visible";
$("#innerBox2").css("visability", "visible");
}
</script>
</body>
</html>

→ 버튼 클릭 시 나타남
3-4. DOM 추가하기 (Ajax로 코드 간결화)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
border: 1px solid black;
padding: 10px;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<h1>추가하기</h1>
<button onclick="addAppend()">append로 추가하기</button>
<button onclick="addPrepend()">prepend로 추가하기</button>
<button onclick="addBefore()">before로 추가하기</button>
<button onclick="addAfter()">after로 추가하기</button>
<div class="box" id="outerBox">
</div>
<script>
function render(id, text) {
return `<div class="box" id="${id}"> ${text}</div>`;
}
function addAppend() {
let box = render("inner1", "내부박스1");
$("#outerBox").append(box)
/*
let newEl = document.createElement("div"); // 빈 dom 생성
newEl.setAttribute("class", "box");
newEl.setAttribute("id", "innerBox1");
newEl.innerHTML = "내부박스1";
let el = document.querySelector("#outerBox");
el.append(newEl);
*/
}
function addPrepend() {
let box = render("inner2", "내부박스2");
$("#outerBox").prepend(box);
/*
let newEl = document.createElement("div");
newEl.setAttribute("class", "box");
newEl.setAttribute("id", "innerBox2");
newEl.innerHTML = "내부박스2";
let el = document.querySelector("#outerBox");
el.prepend(newEl);
*/
}
function addBefore() {
let box = render("outer1", "외부박스1");
$("#outerBox").before(box);
}
function addAfter() {
let box = render("outer2", "외부박스2");
$("#outerBox").after(box);
}
/*
function addBefore() {
let newEl = document.createElement("div");
newEl.setAttribute("class", "box");
newEl.setAttribute("id", "innerBox3");
newEl.innerHTML = "내부박스3";
let el = document.querySelector("#outerBox");
el.before(newEl);
}
function addAfter() {
let newEl = document.createElement("div");
newEl.setAttribute("class", "box");
newEl.setAttribute("id", "innerBox4");
newEl.innerHTML = "내부박스4";
let el = document.querySelector("#outerBox");
el.after(newEl);
}
*/
</script>
</body>
</html>
- append : 차례대로 쌓임 - 내부박스1
- prepend : 최신순으로 쌓임 (댓글 등록 구현 시 사용) - 내부박스 2
- before : 내부 박스 외부에 최신순으로 쌓임 - 외부 박스1
- after : 내부 박스 외부에 차례대로 쌓임 (오래된 순) - 외부 박스2

3-5. DOM 삭제하기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
border: 1px solid black;
padding: 10px;
}
</style>
</head>
<body>
<h1>삭제하기</h1>
<button onclick="del()">remove로 삭제하기</button>
<div class="box" id="outerBox">
<div class="box" id="innerBox1"> 내부박스1
</div>
</div>
<script>
function del() {
let el = document.querySelector("#innerBox1");
el.remove();
}
</script>
</body>
</html>
- 삭제 전

- 삭제 후 (클릭 후)

3-6. DOM List 추가하기 - 반복문으로 리스트 만들기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
border: 1px solid black;
padding: 10px;
}
.card {
border: 1px solid lightgray;
box-shadow: 0 4px 4px 0 grey;
padding: 10px;
margin: 5px;
border-radius: 5px;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<h1>반복문으로 리스트 만들기</h1>
<button onclick="render()">render</button>
<div class="box" id="outerBox">
</div>
<script>
// 1. 그림 그리기
function render() {
for (let i = 1; i < 5; i++) {
$("#outerBox").append(makeCard(i));
}
}
// 2. DOM 만들기
function makeCard(id) {
return `<div id="card-${id}" class="card">
<h3>제목${id} 입니다</h3>
<p>내용${id} 입니다</p>
<button onclick="del(${id})">삭제</button>
</div>`;
}
function del(id) {
$(`#card-${id}`).remove();
}
</script>
</body>
</html>
- Render 버튼 클릭으로 box 생성 (for문으로 5개 미만으로 생성 - 총 4개)

- 이후 해당 card-{id} 삭제 시 해당 번호 삭제

3-7. Fetch with Ajax
- 설명은 주석에 추가해서 한 번에 정리
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<div id="root">
</div>
<script>
function makeDom() {
return `<div>그림</div>`;
}
function download() {
const xhr = new XMLHttpRequest();
xhr.open("GET", "http://localhost:8080/test", false); // false는 동기 요청을 의미함
xhr.send();
return xhr;
}
$("#root").append(makeDom());
$("#root").append(makeDom());
let xhr = download();
$("#root").append(`<div>${xhr.responseText}</div>`);
$("#root").append(makeDom());
</script>
</body>
</html>
4:06
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<div id="root">
</div>
<script>
function makeDom() {
return `<div>그림</div>`;
}
async function download() { // 비동기로 실행 되야 함 -> 1. 무거운 코드를 함수로 만들어서 분리 / 2. 비동기 함수로 수정 /
let response = await fetch("http://192.168.0.99:8080/test");
// 이런 통신 방법은 io가 일어남 = 오래 걸림 -> 즉 이런 작업들은 실행 시 Promise(어음=pending)를 줌
// promise 객체 -> response 부분에 promise가 아닌 결정체를 받고싶음
// 즉 promise를 안 받기 위해서 await 사용 -> 5초 걸린 후 리얼 값을 넘김. 5초 후 json으로 파싱.
// 여기서 async (비동기함수)를 걸면 5초 걸리는 부분을 체크포인트로 잡고 함수를 빠져나옴
// 빠져나오면 메모리는 일(다운)을 계속 하고 있고 cpu는 그 밑의 라인들 실행 ~ 이후 할 일 없으면 await로 다시 back
//
let data = await response.json(); // 파싱 -> 5초 후 들어와서 5초 후 실행
$("#root").append(`<div>${data.body}</div`);
}
$("#root").append(makeDom());
$("#root").append(makeDom());
download();
$("#root").append(makeDom());
</script>
</body>
</html>
Share article