프로그래밍-학습기록/Javascript

고차함수를 활용한 이벤트리스너 부착과 제거

leesche 2021. 3. 8. 22:31

아래 코드는 캘린더의 날짜를 출력함과 동시에 이벤트리스너를 붙이고 (다음 달로 넘어갈 때, 다시 이벤트리스너를) 제거하고, 새로운 날짜에 대한 이벤트리스너를 붙이는 기능을 구현한 것의 일부이다.

export default class CalendarController {
/* ... */
    #dateOfCalendarClickEventListenerRepository = {};
/*
...
다른 메서드들
...
*/
#printDates() {
    for (/* 캘린더 날짜 하나씩 순회하는 조건 */) {
      /* 캘린더 날짜 하나씩 텍스트를 채워넣는 반복문 */

      const handleClickDateOfCalendar = createHandleClickDateOfCalendar(
        dateOfCalendar,
        $dateElement,
        this
      );
      $dateElement.addEventListener("click", handleClickDateOfCalendar);
      this.#dateOfCalendarClickEventListenerRepository[
        indexForDate
      ] = handleClickDateOfCalendar;
    }
  }
/*
...
*/
}

이벤트리스너를 제거하려면 콜백 함수 이름을 알아야 하기에 따로 선언해둔 객체(dateOfCalendarClickEventListenerRepository)에 그 날짜를 키 값으로 저장했다.

#resetDates() {
    const totalCalendarCells = $allDatesInCalendar.length;
    for (let i = 0; i < totalCalendarCells; i++) {
      $allDatesInCalendar[i].textContent = "";
      $allDatesInCalendar[i].className = "";
      $allDatesInCalendar[i].removeEventListener(
        "click",
        this.#dateOfCalendarClickEventListenerRepository[i]
      );
    }
  }

그리고 이후 달력을 이동할 때, 새로운 달력이 생성되고 이전의 이벤트리스너를 사라져야 한다. 따라서 이전에 저장했던 순서대로 객체에 담긴 콜백함수를 인자로 이벤트리스너를 삭제해준다. 

export const createHandleClickDateOfCalendar = (
  dateOfCalendar,
  $dateElement,
  calendarController
) => {
  return () => {
        /*
        날짜를 클릭했을 때 위 인자들을 활용한 동작을 구현
        */
  };
};

콜백 함수의 경우, 날짜마다 할당된 dateOfCalendar를 콜백 함수가 기억해두도록 하기 위해, 클로저 현상이 일어나도록 함수를 리턴하는 고차 함수를 활용했다.

  • 고차함수를 사용하지 않는다면 어떻게 활용할 수 있을까?
    • 모든 dateOfCalendar 인스턴스를 모아놓은 YearRepository 클래스에 getDateOfCalendar(year, month, date)와 같은 연, 월, 일로 해당dateOfCalendar 인스턴스를 얻는 메서드를 구현하면 될 것 같다.