const sayHello = () => {
return function(){
console.log('hello');
}
}
console.log(sayHello);
const myFunc = sayHello();
console.log(myFunc);
myFunc();
hap = (a,b) => {
return a+b;
}
const add = hap;
console.log(add);
console.log(hap);
const createStore = () => {
let state; // 상태관리
let handlers = [];
// 함수 안에 함수를 또 선언할 수 있다
const send = () => {
}
const subscribe = (handler) => { // (함수를 통해) 나를 구독해줘
handlers.push(handler); // 영속성, 유지 (너의 구독을 기억해줄게. 계속 컨텐츠 만들어서 너에게 알려줄게, push해줄게)
}
return {
send,
subscribe,
}
}
const store = createStore();
console.log(store);
store.subscribe(() => {
console.log('subscribe');
});
store.send();
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>호이스팅 이슈에 대해서</title>
<script src="hoisting.js"></script>
</head>
<body>
<!-- ul>li{button}*3 -->
<ul>
<li>button1</li>
<li>button2</li>
<li>button3</li>
</ul>
</body>
</html>
<let으로 선언>
const btns = document.querySelectorAll("ul li");
console.log(typeof btns); // 너는 array (li 2개 이상인 것 보고 관리하기 위해 자동으로 배열인 것을 인식함?)
console.log(btns.length); // 왜냐하면 length가 적용되니까
for(let i=0;i<btns.length;i++){
btns[i].addEventListener('click',(event) => {
console.log(event.target);
console.log(i);
})
}


Q. ES5 시절에는 어떻게 호이스팅 이슈를 피해갔을까?
▶ 즉시실행함수를 사용해서 괄호로 가두고, 파라미터로는 i를 받지만 가둬진 파라미터 자리에는 index 변수를 사용해서 호이스팅이 발동하는 변수 i 값이 아니라, 오염되지 않는 index를 사용함으로써 문제를 해결<즉시실행함수 구조> (function(x){ // 실행문 })(파라미터);*즉시실행함수: 자기자신을 정의하자마자 즉시 실행되는 함수
const btns = document.querySelectorAll("ul li");
for(var i=0;i<btns.length;i++){
((index)=>{
btns[index].addEventListener('click',(event) => {
console.log(index);
})
})(i); // 즉시실행함수 처리한 부분
} // end of for
배열(Array): 연관된 값들을 하나의 그룹으로 묶어서 나열한 자료구조 -> Map
배열 공부 로드맵: (배열이 제공하는)내장함수 → 얕은 복사와 깊은 복사+ forEach문(자바에는 없음)
(프론트엔드에 생각이 있다면, 백엔드 도움(지원) 없이 단독으로 테스트해 볼 수 있으면 좋음)
얕은 복사
- 객체의 얕은 복사는 복사본의 속성이 복사본이 만들어진 원본 객체와 같은 참조 (메모리 내의 같은 값을 가리킴)를 공유하는 복사
- 따라서 원본이나 복사본을 변경하면, 다른 객체 또한 변경될 수 있음(원본과 복사본이 완전히 독립적인 깊은 복사의 동작과 대조적)
깊은 복사- 복사본의 속성이 복사본이 만들어진 원본 객체와 같은 참조(메모리 내의 같은 값을 가리킴)를 공유하지 않는 복사
- 따라서 원본이나 복사본을 변경할 때, 다른 객체가 변경되지 않는 것을 보장할 수 있음
toString() : 배열을 문자로 변환
join() : 구분자를 활용해 문자열로 이어붙이기
pop() : 배열의 마지막 요소 제거(리턴값으로 잘라낸 요소 반환)
push() : 배열의 끝부분에 새로운 요소 추가(리턴값으로 배열의 길이 반환)
shift() : 배열의 첫 부분 요소 제거(리턴값으로 잘라낸 요소 반환)
unshift() : 배열의 첫 부분에 새로운 요소 추가(리턴값으로 길이 반환)
splice(삽입위치, 잘라낼 갯수, 추가할 내용) : 배열에 새로운 요소를 잘라서 붙임
concat() : 두 개의 배열 합치기
slice() : 배열 잘라내기- 새로운 배열을 만들어서 잘라내기
// forEach문
const colors = ["red","blue","green"]
console.log(colors);
colors.forEach((color) => { // JSON 포맷 다루기
console.log(color);
})
console.log(colors[1]);
console.log(colors[2]);
console.log(colors[0]);
colors.map((color) => console.log(color));
const arr1= ["a","b","c"];
let cnt = 0;
arr1.forEach(function(element){
console.log(`element ===> ${element}`);
cnt++
})
console.log(cnt);
const names = ["나신입","강감찬","이성계"]
const copy = [] // 배열이 제공하는 내장함수
// 얕은 복사, 깊은 복사
for(let i=0;i<names.length;i++){
copy.push(names[i])
console.log(`copy[${i}]:${copy[i]}`);
}
// 하나가 더 생긴 것이기 때문에 깊은 복사
copy.push("나초보")
console.log(copy);
console.log(names);
names.forEach(function(element){
console.log(`element ===> ${element}`);
cnt++
})
<!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>
<h3>시작</h3>
<script>
const fruits = ['🍓','🍎','🍉'];
fruits.forEach((element, cnt) => {
console.log(cnt, element);
// document는 forEach1.html 문서 전체를 받는 객체
document.write(cnt, element) // 브라우저에 js 코드를 가지고 태그나 문자를 쓴다
// 자바를 가지고도 브라우저 쓴다가 된다면 웹서비스를 제공할 수 있지 않나? (여기서 나온 게 Servlet)
})
</script>
<h3>끝</h3>
</body>
</html>
const fruits = ['🍓','🍎','🍉'];
fruits.forEach(element => console.log(element))
fruits.forEach((element, cnt) => console.log(cnt, element))
fruits.forEach((element, cnt, fruits) => console.log(cnt, element, fruits))
fruits.forEach((element, cnt) => {
console.log(cnt, element);
document.write(cnt, element)
})
/*
내장함수-1
: UI만 가지고도 단위테스트를 할 수 있다
splice & slice -> 얕은 복사인가 아님 깊은 복사인가
*/
const names = ["나신입","강감찬","이성계"]
const result = names.toString();
console.log(result);
// join - DOM API(가독성 안좋아) -> 문자열 템플릿으로 만들어서 쓰자 -> 최소한 DOM Tree 보인다
const result2 = names.join("+");
console.log(result2);
names.splice(1,0,'나초보')
console.log(names);
const other = names.slice(1)
console.log(names);
console.log(other);
other.push('강호동');
console.log(other);
console.log(names);
/*
sort() : 알파벳순으로 요소 정렬
reverse() : 역순으로 요소 정렬
sort((a,b) => {return a-b}) : 올림차순으로 정렬
sort((a,b) => {return b-a}) : 내림차순으로 정렬
sort((a,b) => {return a-b})[0] : 최소값 반환
sort((a,b) => {return b-a})[0] : 최대값 반환
*/
const names = ["나신입","강감찬","이성계"];
console.log(names.sort());
const nums = [5,11,3,1,25];
nums.sort(function(a,b){
return a - b;
})
// arrow function으로 바꾼다면?
nums.sort((a,b) => a-b)
console.log(nums);
<콜백함수를 쓰지 않았을 때>
/*
모든 업무(처리)에는 순서가 있다
입력 -> 처리 -> 출력
순서대로
*/
first = () => {
console.log('1');
}
second = () => {
console.log('2');
}
first();
// first가 지연 발생
second();
<콜백함수 사용>
/*
콜백함수 - 함수의 파라미터 자리에 들어가는 함수 - prototype
용도: 반드시 순서가 지켜져야만 하는 경우에 사용하자
*/
first = (param) => {
console.log('1');
param();
}
second = () => {
console.log('2');
}
first(second);
// 전개연산자
// spread operator를 이용해서 배열을 복사하면 깊은 복사이다
let dept = {
deptno: 10,
dname: '총무부',
loc: '부산'
}
let emp = {
empno: 7566,
ename: '강감찬'
}
let newObject = {...dept, ...emp}
console.log(newObject);
let depts = [
{deptno: 10, dname: '총무부', loc:'부산'},
{deptno: 20, dname: '개발부', loc:'서울'},
{deptno: 30, dname: '인사부', loc:'인천'}
]
let depts2 = [...depts,{ deptno:40, dname:'운영부', loc:'제주'}]
console.log(depts2);
let depts3 = [...depts2, {deptno:50}]
console.log(depts3);
depts.forEach(dept => console.log(dept))
depts.forEach((dept, index) => {
if(index === 1){
console.log(dept);
console.log(dept.dname);
console.log(dept['loc']);
}
}) // end of forEach
depts.map((dept, index, arr) => { // map - es6
console.log(dept);
console.log(index);
console.log(arr);
})
const names = ["나신입","강감찬","이성계"]
const names2 = [...names, "나초보"]
const names3 = ["나신입","강감찬","이성계"]
console.log(names2);
console.log(names); // 깊은 복사
console.log(names == names2); // false
console.log(names === names2); // false
console.log(names == names3); // 주소번지 비교 // false
console.log(names === names3); // false
let depts = [{
0:{deptno: 10, dname: '총무부', loc:'부산'},
1:{deptno: 20, dname: '개발부', loc:'서울'},
2:{deptno: 30, dname: '인사부', loc:'인천'}
}]
let depts2 = [
{
0:{deptno: 10, dname: '총무부', loc:'부산'},
1:{deptno: 20, dname: '개발부', loc:'서울'},
2:{deptno: 30, dname: '인사부', loc:'인천'}
},
{
0:{deptno: 10, dname: '총무부', loc:'부산'},
1:{deptno: 20, dname: '개발부', loc:'서울'},
2:{deptno: 30, dname: '인사부', loc:'인천'}
}
]
// 유사배열도 가능한가, 아닌가?
// 순수배열만 가능한가?
const depts3 = JSON.stringify(reponse)
depts.map((dept, index) => {
if(index === 0){
console.log(dept);
console.log(dept.dname); // 해결해보기
console.log(dept[0]);
console.log(dept['loc']); // 해결해보기
console.log(dept[0]['loc']);
console.log(dept[0].loc);
console.log(dept[1]['loc']);
}
}) // end of forEach
console.log(dept.dname); // undefined
console.log(dept['loc']); // undefined
-> 해결해보기
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>이벤트이해</title>
<script src="이벤트이해.js" defer></script>
</head>
<body>
<a href="#">링크</a>
</body>
</html>
<!--
1. 사용자가 발생시키는 이벤트
: click, mouseover, mousemove, scroll, mousewheel, keypress, keydown, keyup
2. 시스템이 발생시키는 이벤트
: load, error
이벤트 연결 방법
1. 이벤트 핸들러 이용하는 방법
DOM요소.onClick = () => {}
DOM요소.onKeyup = () => {}
2. 내장함수를 이용하는 방법
: 두 번째 파라미터에 있는 함수를 콜백함수라 하고
: 이벤트명에 해당하는 이벤트가 발동하면 콜백함수가 자동으로 실행된다
DOM요소.addEventListener('이벤트명{on뺀}',() => {}: 콜백함수)
-->
const a = document.querySelector('a');
console.dir(a);
// 이 때는 '링크클릭 다시'만 출력
a.onclick = () => {
console.log('링크클릭');
}
a.onclick = () => {
console.log('링크클릭 다시');
}
// 여기서는 'you click','you click again' 둘 다 출력
a.addEventListener('click',() => {
console.log('you click');
})
a.addEventListener('click',() => {
console.log('you click again');
})
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>이벤트 발생 대상</title>
<script defer src="이벤트발생대상.js"></script>
<link rel="stylesheet" href="이벤트발생대상.css" />
</head>
<body>
<main>
<section>
<article>
<nav>
<div></div>
</nav>
</article>
</section>
</main>
</body>
</html>
* {
margin: 0px;
padding: 0px;
box-sizing: border-box;
}
main {
width: 100%;
height: 100vh;
padding: 70px;
background-color: #ddd;
}
main section {
width: 100%;
height: 100%;
padding: 70px;
background-color: #bbb;
}
main section article {
width: 100%;
height: 100%;
padding: 70px;
background-color: #999;
}
main section article nav {
width: 100%;
height: 100%;
padding: 70px;
background-color: #777;
}
main section article nav div {
width: 100%;
height: 100%;
padding: 100px;
background-color: #555;
}
/*# sourceMappingURL=style.css.map */
/*
이벤트가 발생한 대상 알아내기
e.target: 이벤트가 발생했을 때 마우스 포인터 위치에 있는 요소를 반환한다
e.currentTarget:
이벤트가 발생했을 때 이벤트문 상에서 선택자 요소를 반환
*/
const main = document.querySelector("main");
main.addEventListener('click', (e)=>{
console.log(e.currentTarget);
console.log(e.target);
})
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>실습 - submit 이슈</title>
<script>
function login(){
console.log(event.target);
console.log('로그인 호출 성공');
document.getElementById('f_login').submit();
}
</script>
</head>
<body>
<form id="f_login" method="get" action="./sumitAction.html">
<input type="text" name="mem_id" id="mem_id">
<input type="button" value="로그인" onclick="login(event)">
<button>로그인2</button>
</form>
</body>
</html>
<div class="row mt-5 justify-content-end">
<div class="col-6 col-md-4">
<form name="frm">
<div class="input-group">
<input type="text" name="query" class="form-control" value="자바" />
<button class="btn btn-danger">검색</button>
</div>
</form>
</div>
</div>
<hr />
<div class="row" id="list_book"></div>
<div class="text-center mt-2">
<button class="btn btn-primary btn-sm px-5" id="prev">이전</button>
<span id="page" class="px-3">1/10</span>
<button class="btn btn-primary btn-sm px-5" id="next">다음</button>
</div>
<script>
const bookList = () => {
$.ajax({
type: 'get',
url: 'https://dapi.kakao.com/v3/search/book?target=title&query=오라클&size=5',
headers: { Authorization: 'KakaoAK f5cf55f8716c9f2476806404e4b45b59' },
data: { query: '자바', page: 1, size: 5 },
dataType: 'json',
success: function (data) {
console.log(data); // [object Object] -> JSON.stringify()
},
error: function (error) {
console.log(error); // 디버깅시 힌트를 얻기 위해서
},
}); // end of 비동기통신 처리
}; // end of bookList()
bookList();
</script>