JavaScript에서 함수는 1급 객체이다

이수빈·2023년 4월 7일
1

Html, Css, JS

목록 보기
2/7


JavaScirpt에서의 함수?

  • 함수가 1급객체인 특성을 이용해 setInterval을 통한 Clean Up 작업을 전역상태로 처리한 코드를 정리하고자 한다.

  • 구현해야 했던 기능은 React Native를 통해 만든 앱에서 게임이 진행되는 전체 시간초를 count해야했던 기능이였다.

  • 먼저 기반이 되는 배경지식들부터 알아보자.

함수는 1급 객체이다


  • JS는 다른 언어들과 달리 함수를 1급객체로 취급한다.

    그렇다면 1급 객체란 무슨 뜻일까?

  • JS Deep Dive에서는 다음과 같은 조건을 만족하는 객체를 1급객체라 말한다.

    1. 무명의 리터럴로 생성할 수 있다.(익명함수) 즉 런타임에 생성이 가능하다.
    2. 변수나 자료구조(객체, 배열)에 저장 할 수 있다.
    3. 함수의 매개변수에 전달 할 수 있다.
    4. 함수의 반환값으로 사용 할 수 있다.
  • JS의 함수는 일급객체이므로 값처럼 사용할 수 있다. 이런 일급객체의 특성은 JS로 하여금 함수형 프로그래밍을 가능하게 한다.


일급객체의 특성을 활용한 코드

  • 먼저 전체 문제를 해결한 전체 시간을 count 해야 했는데, 이를 위해 문제풀이가 시작되었을 때 useEffect를 통해 setInterval 이벤트를 등록해야 했다.

  • setInterval을 clean Up 하는 함수를 반환하는 클로저를 만들고, useEffect를 통해 컴포넌트가 마운트 되었을 때 Interval 이벤트를 등록한다. 클로저에서는 Interval마다 atom의 Duration Time을 update한다.

  • 결과를 출력하고 이벤트 핸들러를 cleanUp 하는 과정은 마지막 Screen에서 이루어져야한다. 이를 위해 Recoil을 사용하였고, atom을 만들어 CleanUp Fn과 시간초를 atom에 저장했다.

//SecondScreen1.js

const SecondScreen1 = ({ navigation, route }) => {

    const { params: { categoryId } } = route;
    const [durationTime, setDurationTime] = useRecoilState(DurationTime);
    const [durationCleanup, setDurationCleanup] = useRecoilState(DurationCleanUp);
  
  ...
  
     const countClosure = () => {
        const countProgress = setInterval(() => {
            setDurationTime(current => current + 1);
        }, 1000);

        return () => clearInterval(countProgress);
    };


    useEffect(() => {
        axios.get(`http://13.124.233.9:8080/categories/${categoryId}/questions?page=0`)
            .then(({ data }) => {
                console.log(data);
                setfullItems(data);
                setAnswerList(data.answers);
                setLoading(false);
                const arr = data.answers
                arr.map((item) => {
                if (item.isCorrect === true) {
                    setSolution(item.content)
                }
                })
            })
            .catch((err) => console.log(err))


        const cleanUp = countClosure();
        setDurationCleanup({ cleanUpFn: cleanUp });

    }, []);
  
  return(
    ...
    )

  • atom은 다음과 같다.
//atom.js

import {
    atom,
} from 'recoil';

export const DurationTime = atom({
    key: 'DurationTime', 
    default: 0,
});

export const DurationCleanUp = atom({
    key: 'DurationCleanup',
    default: { cleanUpFn: '', }
})
  • 마지막 결과창이 나오기전 Screen에서 컴포넌트가 Unmount 될때 CleanUp을 해준다.
// SecondScreen4.js

const SecondScreen4 = ({ navigation }) => {
  const [durationCleanup, setDurationCleanup] = useRecoilState(DurationCleanUp);
  
  ...
   useEffect(() => {
        axios.get(`http://13.124.233.9:8080/categories/5/questions?page=3`)
            .then(({ data }) => {
                setfullItems(data);
                setAnswerList(data.answers);
                setLoading(false);
                const arr = data.answers
                arr.map((item) => {
                    if (item.isCorrect === true) {
                        setSolution(item.content)
                    }
                })
            })
            .catch((err) => console.log(err))

        return durationCleanup.cleanUpFn(); // 
    }, []);
  • 결과창에서는 문제를 푸는데 걸린시간을 보여주고 컴포넌트가 unMount될때 재시작을 위해 시간초를 초기화한다.
// LastScreen.js

const LastScreen = ({ navigation }) => {
    const [durationTime, setDurationTime] = useRecoilState(DurationTime);


  useEffect(() => {

    return () => setDurationTime(0);
  }, [])
  
  return (
  ...
  <Text style={{ color: "#3498DB" }}>{durationTime}</Text>가 걸렸어요
  ...
  )

}
  • 이렇게 객체의 프로퍼티에 함수를 넣는것은 JS에서 함수가 일급객체로 취급되기 때문에 가능한 일이다.

ref)
JS DeepDive 18장 함수와 일급 객체

profile
응애 나 애기 개발자

0개의 댓글