(33) 23.11.08[JS]

DANA·2023년 11월 8일

KDT-구디아카데미

목록 보기
33/56

고차함수.js

  • 고차함수 - 반환형으로 함수를 사용할 수 있다
  • 고차함수는 리턴에 오는 값이 함수이니까 이것을 호출하려면 할당연산자로 일단 받아내고(return function(){}) - [Function:익명]
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);

구독발행모델.js

  • 함수 안에 함수 선언이 가능하다 - 일급함수
  • 어떤 컨셉인가? → 리덕스의 근간이 되는 FLUX라는 아키텍쳐가 있음
  • {} -> 뭐가 떠올라? const sonata = {carColor:'검정', speed:0}
  • 콤마(,)는 열거형 연산자 -> ES6에서 스레드 연산자에서 열거형 연산자 얘기가 나옴
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();

호이스팅이슈

  • hoisting: 블록 안에서 선언된 지역변수가 코드블록 밖으로 끌어 올려지면서 강제로 전역변수화 되는 현상
    (이전에는 즉시 실행으로 문제를 해결했었음)

hoisting.html

<!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>

hoisting.js

  • ES5에서는 변수 선언할 때 var를 선언했지만, 호이스팅 이슈 차단을 위해 ES6부터는 let으로 사용
<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);
  })
}
  • let 결과(버튼을 누르면 0, 1, 2)
  • var로 선언
    : let 대신에 var를 사용하면 0,1,2까지 간 다음 마지막에 3이 전역에 등록되면서 0번째, 1번째, 2번째 버튼에도 3이 출력됨

Q. ES5 시절에는 어떻게 호이스팅 이슈를 피해갔을까?
▶ 즉시실행함수를 사용해서 괄호로 가두고, 파라미터로는 i를 받지만 가둬진 파라미터 자리에는 index 변수를 사용해서 호이스팅이 발동하는 변수 i 값이 아니라, 오염되지 않는 index를 사용함으로써 문제를 해결

  <즉시실행함수 구조>
  (function(x){
    // 실행문
  })(파라미터);

*즉시실행함수: 자기자신을 정의하자마자 즉시 실행되는 함수

hoisting2.js

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() : 배열 잘라내기- 새로운 배열을 만들어서 잘라내기

배열1.js

// 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++
})
  • 깊은 복사: 새로운 배열을 추가
  • 얕은 복사: 주소번지가 같은 거니까 한 쪽을 바꾸면 다른 쪽도 바뀐다(오염)

forEach문

매개변수

  • callbackFn: 배열의 각 요소에 대해 실행할 함수입니다. 반환값은 사용되지 않습니다. 함수는 다음 인수를 사용하여 호출됩니다.
  • element: 배열에서 처리 중인 현재 요소
  • index: 배열에서 처리 중인 현재 요소의 인덱스
  • array: forEach()를 호출한 배열

forEach1.html

<!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>

forEach1.js

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.js

/* 
  내장함수-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);

내장함수2.js

  • Array.prototype.sort(): 배열의 요소를 적절한 위치에 정렬한 후 그 배열을 반환
  • 매개변수: compareFunction(Optional)
    정렬 순서를 정의하는 함수. 생략하면 배열은 각 요소의 문자열 변환에 따라 각 문자의 유니 코드 코드 포인트 값에 따라 정렬됩니다.
/* 
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);

콜백함수

콜백1.js

<콜백함수를 쓰지 않았을 때>
/* 
  모든 업무(처리)에는 순서가 있다
  입력 -> 처리 -> 출력
  순서대로
*/

first = () => {
  console.log('1');
}

second = () => {
  console.log('2');
}

first();
// first가 지연 발생
second();

콜백2.js

<콜백함수 사용>
/* 
  콜백함수 - 함수의 파라미터 자리에 들어가는 함수 - prototype
  용도: 반드시 순서가 지켜져야만 하는 경우에 사용하자
*/

first = (param) => {
  console.log('1');
  param();
}

second = () => {
  console.log('2');
}

first(second);

전개구문

전개1.js

// 전개연산자
// 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

전개2.js

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

-> 해결해보기

  • 객체 리터럴 복습하기

로그인화면 구현

  • 인증

이벤트 처리

이벤트이해.html

<!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뺀}',() => {}: 콜백함수)
 -->

이벤트이해.js

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');
})

이벤트발생대상.html

  • 캡쳐링, 버블링: 이벤트 처리할 때 고려해야 함
<!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>

이벤트발생대상.css

* {
  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 */

이벤트발생대상.js

/* 
이벤트가 발생한 대상 알아내기
e.target: 이벤트가 발생했을 때 마우스 포인터 위치에 있는 요소를 반환한다

e.currentTarget:
이벤트가 발생했을 때 이벤트문 상에서 선택자 요소를 반환
*/
const main = document.querySelector("main");

main.addEventListener('click', (e)=>{
  console.log(e.currentTarget);
  console.log(e.target);
})

submit.html

<!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>
  • submit 호출을 통해 일부러 가게 한 것임
    -> 월요일에 다시 진행할 것

카카오API 도서

  1. 로그인 후 - 우상단 내 어플리케이션 - 어플리케이션 추가하기
  • 앱이름: gdu_20230918 / 사업자명: 본인 이름 / 카테고리: 교육 - 체크 후 저장
    프로젝트 들어가서 앱키 저장해놓기
  1. 왼쪽 메뉴 플랫폼 - 웹 플랫폼 등록 -
    http://localhost:9000
    http://localhost:3000 - (2개 한꺼번에 적기)저장
  2. 상단메뉴 - 문서 - 좌상단 Daum 검색하기 - rest API - 밑으로 쭉 내려서 책 검색하기
  1. postman 등록

bookList.ejs

<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>

0개의 댓글