- Published on
함수 표현식 !== 함수 선언식
- Authors
- Name
- 박준열 | Eric Park
자바스크립트에는 함수를 선언하는 방식이 여러가지가 있는데, 오늘은 대표적인 두가지와 호이스팅이 발생하는 상황에서 두가지의 차이점에 대해 간단히 알아보려 한다.
함수 선언문 (Function Declaration)
함수를 만드는 가장 대표적인 방법이자, 다른 언어들과 가장 유사한 방법이다. 나도 처음에 다른 언어를 쓰다가 자바스크립트를 접했을 때는 함수 선언문만 이용했었는데, 방식들간의 차이점을 알게된 후로는 많이 쓰지는 않는 것 같다.
function fn() {} //함수 선언문
함수 표현식 (Function Expression)
다른 언어에는 존재하지 않는 자바스크립트의 독특한 방식이다. 다른 언어에서는 함수의 이름을 정해서 함수 선언문처럼 선언을 하지, 함수 표현식처럼 변수에 함수를 할당하지는 않는다.
하지만 이 모든 것이 가능한건 자바스크립트에서 함수는 일급 객체이기 때문.. 자바스크립트가 다른 언어에 비해 헷갈리는 언어인 이유이기도 하다.
var fn = function () {} //함수 표현식
함수 선언문과 함수 표현식의 차이
두 방식의 차이를 알아보려면 호이스팅이 발생하는 상황이 가장 대표적인 예시이기에 가져와봤다.
console.log(sum(1, 2))
console.log(multiply(3, 4))
function sum(a, b) {
return a + b;
}
var multiply = function(a, b) {
return a * b;
}
스크롤을 내리기 전에 이런 코드가 있다고 가정을 하고 출력된 값을 예측해보자. 예측을 하셨으면 내려보셔도 됩니다.
. . . . . . . . . . . . .
일단 결과만 보면
3
Uncaught TypeError: multiply is not a function
이렇게 될 것이다. 그럼 이제 왜 그렇게 되는지를 살펴보자.
호이스팅을 간단하게 생각하면, 모든 변수/함수 등등의 선언을 코드의 최상위단으로 끌어 올려 먼저 실행을 한다고 생각하면 편하다. 물론 이건 생각을 돕는 방식일 뿐, 실제로 이게 작동 방식은 아니다.
호이스팅이 발생했다고 가정하고 코드의 실행 순서를 바꿔보자.
var sum = function(a, b){
return a + b;
}
var multiply;
console.log(sum(1, 2))
console.log(multiply(3, 4))
multiply = function(a, b) {
return a * b;
}
호이스팅으로 인해 코드의 순서가 이런식으로 바뀐다고 보면 된다.
함수 선언문으로 만든 함수인 sum은 초기화와 동시에 함수를 만들고 할당을 하는 반면에 함수 표현식으로 만든 함수인 multiply는 초기화만 진행하고 undefined값이 할당이 된다. 그리고 추후에 실제로 함수가 할당이 되는 줄까지 갔을 때야 multiply 변수에 함수가 할당이 된다.
이러한 순서를 갖기 때문에, console.log(sum(1,2))
는 오류가 나지 않는다. 왜냐면 위에서 sum이라는 변수에 함수가 만들어지고 할당이 되었으니까 문제 없이 함수가 호출이 가능하다.
하지만 console.log(multiply(3, 4))
는 오류가 발생한다. 왜냐면, 함수 표현식으로 만든 함수는 호이스팅이 발생하면 실제로 값이 할당이 되는 줄까지 가기 전에는 undefined로 초기화가 되어있는 상태이기 때문이다. 그래서 console.log(multiply(3, 4))
가 실행되는 상황에서는 multiply는 함수가 아니라 그냥 undefined라는 값이 담긴 변수이기 때문에 함수 호출이 불가능하다.
결론
그럼 두 방식중 어떤 방식이 더 좋은 방식일까??
결론만 말하면 오류가 발생했던 함수 표현식이 더 좋은 방식이다.
이유는 여러가지가 있는데, 개인적으로 가장 큰 이유는
함수 선언문은 디버깅을 훨씬 더 어렵게 만든다.
일반적으로 프로그래머들은 위에서 아래로 코드가 실행이 될 것이라고 예측을 한다. 따라서 함수의 결과를 예측할 때나, 오류가 발생해서 디버깅을 할 때는 일반적으로 위에서부터 차근차근 코드를 읽으면서 추측을 한다. 하지만 함수 선언문으로 함수를 만들면 위에서 갑자기 아직 선언하지도 않은 함수가 실행이 가능한 이상한 상황이 발생한다.
이 상황은 자연스러운 상황이 아니므로 디버깅이 훨씬 까다로워진다.