함수 선언문 vs 함수 표현식

isthis·2022년 4월 10일
0
post-thumbnail

함수 선언문 vs 함수 표현식

함수 선언문은 function 정의부만 존재하고 별도의 할당 명령이 없는 것
함수 표현식은 정의한 function을 별도의 변수에 할당하는 것

함수 선언문의 경우 반드시 함수명이 정의돼 있어야 하는 반면, 함수 표현식은 없어도 된다.
함수명을 정의한 함수 표현식을 ‘기명 함수 표현식', 정의하지 않은 것을 ‘익명 함수 표현식'이라고 부르기도 하는데, 일반적으로 함수 표현식은 익명 함수 표현식을 말한다.

function a () { } // 함수 선언문. 함수명 a가 곧 변수명.
a(); // 실행 OK.

var b = function () { } // (익명) 함수 표현식. 변수명 b가 곧 함수명.
b(); // 실행 OK.

var c = function d () { } // 기명 함수 표현식. 변수명은 c, 함수명은 d.
c(); // 실행 OK.
d(); // 에러.(c 함수 내부에서는 호출 가능)

함수 선언문과 함수 표현식의 가장 큰 차이점은 호이스팅 시에 발생한다.

💡 호이스팅이란?
자바스크립트는 코드를 실행할 때, 현재 실행되는 실행 컨텍스트 내부 전체를 처음부터 끝까지 쭉 훑어나가며 식별자 정보들을 순서대로 수집한다.(매개변수의 이름, 함수 선언, 변수명 등) 이렇게 되면, 코드가 실행되기 전임에도 불구하고 자바스크립트 엔진은 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있게 된다. 이러한 현상을 이해하기 쉽게 ‘자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다'라고 생각하는데, 여기서 ‘끌어올리다’라는 의미의 hoist에 ing를 붙여 호이스팅이라는 개념이 등장한 것이다.

예시 코드를 통해 확인해보자.

console.log(sum(2,5));
console.log(multiply(3,4));

// 함수 선언문 sum
function sum (a, b) {
	return a + b;
}

// 함수 표현식 multiply
var multiply = function (a, b) {
	return a * b;
}

위 코드를 호이스팅된 상태로 변경해보자.

function sum (a, b) { // 함수 선언문은 전체를 호이스팅한다.
	return a + b;
}

var multiply; // 변수는 선언부만 끌어올린다.

console.log(sum(2,5));
console.log(multiply(3,4));

multiply = function (a, b) { // 변수의 할당부는 원래 자리에 남겨둔다.
	return a * b;
}

함수 선언문은 전체를 호이스팅하는 반면, 함수 표현식은 변수 선언부만 호이스팅하였다. 함수도 하나의 값으로 취급할 수 있다는 것이 이런 것이다.

위 코드를 실행시켜보면, sum 함수는 선언 전에 호출해도 아무 문제 없이 실행된다. 이는 어디에 작성해도 오류를 내지 않아서 초급자들이 자바스크립트를 좀 더 쉽게 접근할 수 있지만, 큰 혼란을 일으키는 원인이기도 하다. 인간은 보통 ‘선언한 후에 호출할 수 있다'라고 인식하는 편이 훨씬 자연스럽기 때문이다.

이러한 거부감 외에도 함수 선언문이 혼란스러운 개념인 이유가 있다. 예를 들어보자.

익명의 개발자가 거대한 자바스크립트 파일 내의 100번째 줄에 어떠한 함수를 선언하여 그 함수를 여기저기서 호출해서 활용해왔다. 그런데, 실수로 3000번째 줄에서 같은 이름의 함수를 다시 선언하여 반환 내용을 기존과 전혀 다르게 설정했다고 가정해보자.

전역 컨텍스트가 활성화될 때 전역공간에 선언된 함수들이 모두 호이스팅된다. 따라서 코드를 실행하는 중에 실제로 호출되는 함수는 오직 마지막에 할당한 함수뿐이다. 따라서 위의 경우, 프로그램 이곳 저곳에 문제가 생기게 된다. 그런데 정작 해당 함수는 아무런 에러를 내지 않는 상황이 발생한다.

만약 함수를 모두 함수표현식으로 정의했다면 어땠을까. 3000번 줄 이전까지는 기존의 함수대로, 3000번 줄 이후부터는 이후에 선언한 함수의 내용대로 잘 돌작했을 것이다. 또한, 100번째 줄보다 이전에 해당 함수를 호출하는 코드가 있었다면 그 줄에서 바로 에러가 검출되므로 더욱 빠른 타이밍에 손쉽게 디버깅이 가능했을 것이다.

정리

정리하자면, 함수선언식은 함수표현식에 비해 많은 혼란을 일으킨다.
첫 번째 이유는 선언 전에도 호출이 가능하여 거부감이 들기 때문이다.
두 번째 이유는 함수선언식은 함수 전체가 호이스팅되어 마지막에 할당한 함수만 호출되기 때문에 문제가 발생할 확률이 높기 때문이다.
따라서, 원활한 협업을 위해서는 전역공간에 함수를 선언하거나 동명의 함수를 중복 선언하는 경우가 없어야 한다는 것을 알 수 있다.
또한, 위 예시와 같은 일을 막기 위해 함수 선언문 보다는 함수 표현식을 사용하는 것이 더 유용할 것이다.

참고자료
코어자바스크립트

profile
공부

0개의 댓글