...
자바스크립트의 함수를 리턴하는 함수
클로저에서도 보았고 우리는 자바스크립트 코딩하면서 가끔 함수 자체를 리턴하는 함수를 한번쯤은 보았을 것이다.
function hello(){
return function world(){
return "Hello Word";
}
}
const a = hello();
// == world()
원리는 알겠다. 사용법도 알겠다. 그런데 대체 이러한 기법이 어디에 쓰이는건가? 왜 굳이 값을 리턴하면되지 함수안에 함수를 리턴하는가? 지금부터 return function() {} 의 실용 기법을 알아보자.
일반적인 이벤트 콜백 함수 등록법
여기 버튼이 3개 있는 웹문서가 있다.
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<button id="c1">C1</button>
<button id="c2">C2</button>
<button id="c3">C3</button>
<script>
</script>
</body>
</html>
우리는 저 3개의 버튼마다 다음과 같이 이벤트 리스너를 등록할 예정이다. addEventListenr 두번째 인자에는 함수가 들어가기 때문에 익명함수로 처리해주었다.
<body>
<button id="c1">C1</button>
<button id="c2">C2</button>
<button id="c3">C3</button>
<script>
document.getElementById('c1').addEventListener('click', function(){ console.log(1) });
document.getElementById('c2').addEventListener('click', function(){ console.log(1) });
document.getElementById('c3').addEventListener('click', function(){ console.log(1) });
</script>
</body>
코드 자체에 문제는 없지만 가만 보면 코드 반복이 발생한다. 따라서 동일한 결과를 반환하는 함수를 밖으로 빼서 리팩토링 한다. c 라는 함수를 새로 만들고 이벤트리스너에 등록시키면 된다. 다만 모두 다 알다시피 이벤트 리스너 인자에는 함수 자체가 들어가야 한다. 만일 함수 인자 부분에 c()로 넣게 되면 리턴값 자체가 들어가는 꼴이 되기 때문에 함수 실행이 되지 않기 때문이다.
<script>
function c() {
console.log(1);
}
document.getElementById('c1').addEventListener('click', c);
document.getElementById('c2').addEventListener('click', c);
document.getElementById('c3').addEventListener('click', c);
</script>
이벤트 콜백에 매개변수를 사용해야 할 경우
그런데 만일 스펙이 변경되서, 각 버튼마다 다른 동작을 하도록 구현한다면 어떻게 해야할까? 예를 들어 c1버튼 누르면 1이 출력되게 만들고 c3 버튼 누르면 3이 출력되게 만들고 싶다. 이는 함수에 파라미터를 줘서 파라미터 변수값을 출력해주면 되는 방법이다. 하지만 문제는 어떻게 줄까? 이다.
아래와 같이 하면 앞서 말했다 싶이 리턴값을 넣어버리는 꼴이 된다. 버튼 누르지도 않았는데도 console.log() 함수가 한번 실행하고마는 기적을 볼 수 있을 것이다.
function c(n) {
console.log(n);
}
document.getElementById('c2').addEventListener('click', c(2));
즉, c로 주면 파라미터를 줄수없고, c(2)로 하면 함수 실행이 안되게 된다. 정 방법이 없는걸까? 무식하게 전역변수로 처리할까? 라고 싶지만 사실 간단하다.
함수를 리턴하는 함수를 이용한 클로저
c()로 이벤트리스너 함수에 등록하면 동작이 이상하게 되는 이유는, 이벤트 리스너에는 함수가 등록되는게 아니라 리턴값이 넣어지기 때문이다. 그럼 이 원리를 이용하면 된다. 호출한 함수에서 아예 함수 자체를 리턴 시켜버리면, 리턴값이 곧 함수이게 되고, 이는 곧 함수 등록이 되지 않을까?
function c(n) {
return function(){
console.log(n);
}
}
document.getElementById('c1').addEventListener('click', c(1));
document.getElementById('c2').addEventListener('click', c(2));
document.getElementById('c3').addEventListener('click', c(3));
이렇게 하면 이벤트 리스너는 함수가 리턴된 함수를(클로저 처리가 된) 등록하게 된 꼴이 된다.
화살표 함수로 표현하기
좀더 함수를 리턴하는 함수 코드식을 간결하게 하기 위해 화살표 함수로 나타내면 다음과 같이 표현이 가능하다.
const c = (n) => () => { //화살표 함수가 화살표 함수를 리턴한다.
console.log(n);
}
document.getElementById('c1').addEventListener('click', c(1));
document.getElementById('c2').addEventListener('click', c(2));
document.getElementById('c3').addEventListener('click', c(3));
처음보면 괴상한 문법 표현에 혀를 내두르겠지만 확실히 코드량을 줄이는 기법이니 익숙해 지는 것이 좋다.
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.