[JavaScript] 함수의 표현식과 선언식
이전 노트 변수와 스코프에 이어서 함수의 선언과 관련한 내용을 작성해보자.
Function
자바스크립트에서는 함수를 선언하는 방식이 두가지 존재하는데
함수는 function이라는 명명(선언식)으로 선언하는 방식과 변수를 이용하여 선언(표현식)하는 방식이 있다.
Function의 선언식
함수 선언식은 일반적인 언어에서 사용하는 방식과 비슷하다.
1 | function test() { | 
2 |   return console.log("test함수 실행") | 
3 | } | 
4 | test(); | 
Function의 표현식
함수 표현식은 javascript의 문법으로 변수에 함수를 담는 방식이다.
1 | var test = function() { | 
2 | ... | 
3 | } | 
Function의 표현식 VS 선언식
둘의 차이점은 함수 선언식은 호이스팅에 영향을 받지만, 표현식은 호이스팅에 영향을 받지 않는다.
다음 예제를 보자
1 | test(1,2) // 3 | 
2 | test2(3,4) // Uncaught TypeError: test2 is not a function at <anonymous>:2:1 | 
3 | |
4 | function test(a,b) { | 
5 |   return a + b | 
6 | } | 
7 | var test2 = function(c,d) { | 
8 |   return c + d | 
9 | } | 
위의 예제를 실행하면 test()는 정상동작하지만, test2()는 오류를 발생시킨다.
실제로 자바스크립트 엔진에 의해 다음의 절차로 실행이 된다.
1 | function test(a,b) { | 
2 |   return a + b | 
3 | } | 
4 | |
5 | var test2 | 
6 | |
7 | test(1,2) | 
8 | test(3,4) | 
9 | |
10 | test2 = function(c,d) { | 
11 |   return c + d | 
12 | } | 
결론적으로 함수를 표현식으로 사용하게 될 경우 자바스크립트가 함수로 인식하지 않고 변수로 인식할 가능성이 있다.
때문에 일반적으로 함수를 선언한 후에 실행시켜야 한다는 규칙을 권장하기 때문에 함수 표현식을 지향한다.
또 함수의 표현식의 장점으로 클로저와 콜백함수로 선언식보다 유용하게 쓰인다.
Closure
클로저는 인자를 갖고있지 않아도 외부함수의 인자와 변수에 접근할 수 있는 내부 함수를 말한다.
1 | let a = "1"; | 
2 | function outer() { | 
3 |     let b = "2" | 
4 |     return function() { | 
5 |         let c = "3"; | 
6 |         console.log(a, b, c); | 
7 |     } | 
8 | }; | 
9 | |
10 | const inner = outer(); | 
11 | console.log(inner()); | 
위의 예제에서 inner()를 호출하면 참조할 수 없는 a, b로 인하여 에러가 발생할것 같다.
예제를 풀어보자.
1 | const inner = function() {  | 
2 |     let c = "3"; | 
3 |     console.log(a, b, c); | 
4 | } | 
5 | console.log(inner()); | 
하지만 실제로 정상동작한다.
그 이유는 렉시컬 스코핑이 이루어져 클로저 함수가 리턴된 이후에도 클로저 외부함수의 스코프 영역에 접근할 수 있기 때문이다.
클로저는 함수를 실행하기 전에 해당 함수에 변수를 넘기고 싶을 때에 사용할 수 있다.
1 | const tabs = document.querySelectorAll('.tab'); | 
2 | var i = 0 | 
3 | for(; i < tabs.length; i++) { | 
4 |   tabs.onclick[i] = function(e) { | 
5 |     console.log(i); | 
6 |   } | 
7 | } | 
.tab클래스를 지닌 노드가 3개 있다고 가정하면, 각 노드를 클릭했을 때 결과는 모두 3이 출력된다.
클릭이벤트가 실행된 시점에는 이미 for구문이 끝난 상태이기 때문이다.
이 문제는 값을 할당하는 시점에서 함수를 실행하여 인덱스값을 클로저에 전달하는 방식으로 한다면 해결된다.
1 | function eventHandler(index) { | 
2 |   return function clickEvent(e) { | 
3 |     console.log(index); | 
4 |   } | 
5 | } | 
6 | |
7 | const tabs = document.querySelectorAll('.tab'); | 
8 | var i = 0 | 
9 | for(; i < tabs.length; i++) { | 
10 |   tabs.onclick[i] = eventHandler(i); //함수실행하여 각 클로저에 i값 부여. | 
11 | } | 
콜백함수
함수의 표현식은 임시 변수에 할당하지 않고 콜백함수로도 사용할 수 있다.
콜백함수는 함수 내부에 인자로서 전달하는 함수를 말한다.
1 | var arr = [ 1, 2, 3, 4, 5] | 
2 | arr.forEach(function(data, index) { | 
3 |  console.log(data + index); | 
4 | }) | 
![]()

