본문 바로가기
> 프로그래밍 언어/Javascript

훈훈한 Javascript (16)

by 자몽주스 2023. 9. 16.
728x90
반응형

< 섹션 5 >

1. 함수의 인자와 매개변수

전달인자, 매개변수

웹 스토리지

우선 구현한 것에서 올바르지 않은 날짜를 입력해도

D-day를 입력해주세요 만 뜨는 상태이다.

이 부분때문에 제대로 된 메시지 받지 못하고 있는 것.

이 부분을 고쳐주기 위해서 함수 하나 더 만들어주기.

restTimer 함수 생성

해당 드래그 부분을 restTimer 함수 내부로 이동.

setClearInterval();

이것도 내부에서 사용.

innerHTML 조작하는 부분을 restTimer 함수로 빼 줌으로서

원하는 메시지 출력받을 수 있게 됨

- 이 부분 헷갈림. 어떤 원리인지

 restTimer 로 변경


바로 박스에 날짜 수정해주면 생기는 오류 고쳐주기.

이 함수 자체가 반복실행 되고 있는 것.

1초마다 counterMaker 함수가 반복되고,

input 박스 안에있는 값도 갖고 오게되는 것. (1초마다)

 

그렇기 때문에 날짜를 변경해주게 되면,

1초 뒤에 counter 가 실행되고, 1초 뒤에 다시 한 번 실행되면서 input 안에 박스 dateforMaker 값을 갖고오는 것

 

그래서 카운트 다운 시작 버튼을 다시 눌러주지 않았음에도 불구하고,

카운터가 변화된 것이다.

 

계속해서 dateForMaker 데이터를 갖고오고 있는 것이니,

starter 함수를 실행했을 때만

즉, 버튼을 누른 당시에만

인풋 박스의 데이터들을 갖고오도록 만들어야한다.

( 버튼 누를 때만 위에 시간 값 갖고오도록 )

targetDateInput 이걸 활용.

이걸 갖고와서 starter 함수 내부에 넣어줌.

새로운 날짜 입력했을 때 에러 발생

이유: targetDateInput 이라는 변수를 starter에 갖고옴.

counterMaker 은 더 이상 targetDateInput 이라는 데이터를 사용하지 못하게 됨.

 

함수는 리턴, 반환을 통해서 데이터를 건네주는 것과 

받아오는 것이 가능.

sum 이라는 이름을 가진 함수

따옴표로 감싸져있지 않은 a, b 가 있음.

= 변수로서 동작한다는 뜻. - (이해안됨)

변수로 선언된 a,b가 존재하지않

a, b 는 소괄호 안에서 갖고온다.

sum 실행하기

두 개의 undefined 출력됨.

= 매개 변수 (a, b) 가 어떠한 데이터인지 입력되지 않았기 때문

 

undefined 말고 원하는 데이터를 출력하는 방법

= 전달인자라는 것을 사용해주면 된다.

전달인자 

소괄호 안에 데이터 (10) 을 넣어주게 되면,

첫번 째 콘솔로그 a 가 출력되게 된다. (10)

컴마로 구분해서 데이터 더 넣어줄 수 있음.

 

두 개의 전달인자 전달한 것

 

매개변수와 전달인자는 서로 연결이 되어있는 것.

그리고 순서에 의미가 있다.

sum 함수 실행할 때,  숫자를 순서로 넣어준거면

만들어준 sum 함수에서 a하고 b를 받는다.

 

넣어준 순서에 맞게

각 매개변수로 데이터가 들어온다.

 

함수 내부에서 변수 a 와 b 를 사용할 수 있게 됨.

이렇게 활용할 수도 있다.

다른 숫자 예시

전달인자 부분

매개 변수 부분 (a, b)

 

starter 함수에서 받아온 변수(targetDateInput) 를 counterMaker에서 사용할 수 없던 게 문제였다.

다른 데로(starter함수)로 가져가버려서 counterMaker에서 사용 X

해결방법: 

counterMaker 함수 정의할 때

소괄호 안에 받아올 매개변수 하나 정해준다.

= data로 지정.

확인해보면 undefined 가 뜸

= 매개변수(data) 설정해줬지만,

함수를 실행하는 위치(starter 함수)에서 전달인자 아무것도 설정 안 해줬기 때문.

  const targetDate = new Date(targetDateInput).setHours(0, 0, 0, 0); 

이 부분을

 const targetDate = new Date(data).setHours(0, 0, 0, 0);

이렇게 바꿔주고 출력하면

유효한 시간대가 아니라고 뜬다.

다시 데이터 확인해보면

console.log 잘 찍히다가 undefined 가 찍힌다.

= setInterval 실행할 때, 전달인자 넣어주지 X

data 라는 변수가 undefined 를 담고 있음.

undefined 가 새로운 날짜 객체 데이터를 생성하는데 활용되기 떄문에

Nan 값이 remaining에 담기게 되는 것이고

유효한 시간대가 아닙니다가 출력되게 되는 것.

이거 해결하려면

setInterval 에다가도 전달인자 넣어줘야함.

targetDateInput 전달인자 넣어준다.

그러나, 타이머가 동작하지 않게됨.

  const intervalId = setInterval(() => counterMaker(targetDateInput), 1000);

화살표 함수(이름없는 익명함수)로 넣어주게 된다면,

다시 타이머가 동작하게 됨.

 

전달인자를 넣어서 setInterval 해주고 싶을 땐,

함수내부에 넣어준다음, 함수 내부에서 실행해줘야한다.

실질적으로는 중괄호가 생략된거임.

 

기존 날짜에서 카운트 다운 시작 누른 후

새로운 날짜 입력하고 카운트 다운 시작 누르면 이상하게 동작하는 오류 고치기

여러개의 인터벌이 동시에 동작하기 때문.

starter 함수 실행할 때마다

기존에 있던 interval 모두 삭제해주면 된다.

 

마음에 들지 않는 초 바꿔주기

함수 안에 또 다른 함수 생성.

foramt 함수 생성

time 이라는 매개변수 받아올 것

time 이 숫자 10보다 작다면,

즉 1자리 숫자라면

문자열 0과 time 이라는 매개변수에 담겨져 있는

10보다 작은 숫자를 문자열 형태로 반환. ( 앞에 0 을 붙여서 )

 

for of 사용해서 textContent 부분 변경

remainingTime 변수 생성

remainingTime 찍어보기

날짜들이 계속해서 출력됨.

format 이라는 함수를 실행할 때 그 함수의 전달인자로 넣어주기.

 

한자리 수인 경우에만 반환해주고 있음

한자리 수가 아니라면 아무런 데이터도 remainingTime 에 담기지 않고 있는 것.

 

한자리 수가 아닌경우에도 반환 받을 수 있도록

else 로 넣어준다.

한 자리가 아닌 수는 그대로 사용할 수 있도록 넣어줌.

//페이지 접속하자마자 텍스트 뜨게 하기
const messageContainer = document.querySelector("#d-day-message");
const container = document.querySelector("#d-day-container");
const intervalIdArr = [];

container.style.display = "none";
messageContainer.innerHTML = "<h3>D-Day를 입력해주세요<h3>";
//날짜 입력하는대로 갖고오는 함수
const dateForMaker = function () {
  const inputYear = document.querySelector("#target-year-input").value;
  const inputMonth = document.querySelector("#target-month-input").value;
  const inputDate = document.querySelector("#target-date-input").value;
  //querySelector을 사용해서 태그들을 갖고와줌. 괄호 안에 어떤 태그를 갖고올 지 적어준다.

  //템플릿리터럴
  const dateFormat = `${inputYear}-${inputMonth}-${inputDate}`;
  /*이것과 동일한 코드지만 더 보기에 좋다.
    const dateFormat = inputYear + "-" + inputMonth + "-" + inputDate;*/

  //console.log(inputYear, inputMonth, inputDate);
  return dateFormat;
};

//현재 날짜 데이터(new Date) 갖고오는 함수
const counterMaker = function (data) {
  //리턴 데이터(return dateFormat)가 담겨진 함수(dateForMaker)를 변수에 넣어준다. 그리고 확인
  //const targetDateInput = dateForMaker();

  //현재 날짜 데이터(new Date) 갖고옴
  const nowDate = new Date();
  //targetDateInput(dateForMaker 함수가 담겨있는 변수) 참조(new Date를 사용해서 문자열을 입력)
  const targetDate = new Date(data).setHours(0, 0, 0, 0);
  //현재 시각과 "2023-9-15" 사이의 시간 차이가 ;'밀리초 단위'로 콘솔에 출력

  //시간 차이를 밀리초(ms)에서 "초(seconds)" 단위로 변환
  //날짜 입력하는대로 값을 갖고오는 함수 - 현재 시각
  const remaining = (targetDate - nowDate) / 1000;

  // 만약, remaining 이 0 이라면, 타이머가 종료 되었습니다. 출력
  if (remaining <= 0) {
    container.style.display = "none";
    messageContainer.innerHTML = "<h3>타이머가 종료되었습니다.</h3>";
    messageContainer.style.display = "flex";
    setClearInterval();
    return;
  } else if (isNaN(remaining)) {
    // 만약, 잘못된 날짜가 들어왔다면, 유효한 시간대가 아닙니다. 출력
    container.style.display = "none";
    messageContainer.innerHTML = "<h3>유효한 시간대가 아닙니다.</h3>";
    messageContainer.style.display = "flex";
    setClearInterval();
    return;
  }
  //시간 차이를 초 단위에서 "일(day)/시간(hours)/분(Minutes)/초" 단위로 변환한 값을 저장하는 변수
  const remainingObj = {
    remainingDate: Math.floor(remaining / 3600 / 24),
    remainingHours: Math.floor(remaining / 3600) % 24,
    remainingMin: Math.floor(remaining / 60) % 60,
    remainingSec: Math.floor(remaining) % 60,
  };

  // const documentObj = {
  //   days: document.getElementById("days"),
  //   hours: document.getElementById("hours"),
  //   min: document.getElementById("min"),
  //   sec: document.getElementById("sec"),
  // };

  const documentArr = ["days", "hours", "min", "sec"];
  const timeKeys = Object.keys(remainingObj);
  //const docKeys = Object.keys(documentObj);

  // 초 1초 말고 01초로 나오게 하기
  const format = function (time) {
    if (time < 10) {
      return "0 " + time;
    } else {
      return time;
    }
  };

  // *for of 문 / 이것 또한, 화면에 일, 시간, 분, 초 띄워줌 (D-Day 를 입력해주세요 상단의 시간 표시.)
  let i = 0;
  for (let tag of documentArr) {
    const remainingTime = format(remainingObj[timeKeys[i]]);
    document.getElementById(tag).textContent = remainingTime;
    i++;
  }

  // for in 문 / 화면에 일, 시간, 분, 초 띄워줌 (D-Day 를 입력해주세요 상단의 시간 표시.)
  //let i = 0;
  // for (let key in documentObj) {
  //   documentObj[key].textContent = remainingObj[timeKeys[i]];
  //   i++;
  // }
};

// 움직이는 카운트 다운 기능 만들기
const starter = function () {
  const targetDateInput = dateForMaker();
  container.style.display = "flex";
  messageContainer.style.display = "none";
  setClearInterval();
  counterMaker(targetDateInput);
  const intervalId = setInterval(() => counterMaker(targetDateInput), 1000);
  intervalIdArr.push(intervalId);
};

const setClearInterval = function () {
  for (let i = 0; i < intervalIdArr.length; i++) {
    clearInterval(intervalIdArr[i]);
  }
};

const resetTimer = function () {
  container.style.display = "none";
  messageContainer.innerHTML = "<h3>D-Day를 입력해주세요<h3>";
  messageContainer.style.display = "flex";
  setClearInterval();
};
728x90
반응형