함수 선언문과 함수 표현식의 차이

김영진·2022년 7월 20일
0

TIL

목록 보기
11/29
post-thumbnail

함수 정의란?

함수 정의란 함수를 호출하기 이전에 인수를 전달받을 매개변수와 실행할 문들, 그리고 반환할 값을 지정하는 것을 말한다. 자바스크립트에는 함수를 정의하는 방법이 4가지가 있다

  • 함수 선언문
  • 함수 표현식
  • Function 생성자 함수
  • 화살표 함수

이 중 함수 선언문과 함수 표현식에 대해 알아보고 이 둘의 호이스팅 방식의 차이까지 알아보고자 한다.


함수 선언문

// 함수 선언문
function add(x, y) {
  return x + y;
}

// 함수 호출
console.log(add(2, 5)); // 7

함수 선언문은 함수 리터럴과 형태가 동일하다. 단 함수 리터럴은 함수 이름을 생략할 수 있으니 함수 선언문은 함수 이름을 생략할 수 없다.

식별자의 암묵적 생성

궁금한 점이 있다. add는 함수 몸체 내부에서만 유효한 식별자인 '함수 이름'이므로 add로 함수를 호출할 수 없어야 한다. add라는 이름으로 함수를 호출하려면 add는 함수 이름이 아니라 함수 객체를 가리키는 식별자여야 한다. 그런데 위 예제에서는 식별자 add를 선언한 적도 없고 할당한 적도 없다. add는 결론으로 말하면 자바스크립트 엔진이 암묵적으로 생성한 식별자다.

자바스크립트 엔진은 함수 선언문을 해석해 함수 객체를 생성한다. 이때 함수 이름은 함수 몸체 내부에서만 유효한 식별자이므로 함수 이름과 별도로 생성된 함수 객체를 가리키는 식별자가 필요하다. 따라서 자바스크립트 엔진은 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 거기에 함수 객체를 할당한다.

함수는 함수 이름으로 호출하는 것이 아니라 함수 객체를 가리키는 식별자로 호출한다. 따라서 자바스크립트 엔진은 함수 선언문을 함수 표현식으로 변환해 함수 객체를 생성한다고 생각할 수 있다.


함수 표현식

함수는 일급 객체이므로 함수 리터럴로 생성한 함수 객체를 변수에 할당할 수 있다. 함수 선언문으로 정의한 add를 함수 표현식으로 바꿔서 정의하면 다음과 같다.

var add = function (x, y) {
  return x + y;
}

console.log(add(2, 5)); //7

함수 리터럴의 함수 이름은 생략 가능하다. 일반적으로 함수 표현식에서 함수 이름은 생략한다.

자바스크립트 엔진은 함수 선언문의 함수 이름으로 식별자를 암묵적 생성하고 함수 객체를 할당하므로 함수 표현식과 유사하게 동작하는 것처럼 보이지만, 중요한 차이가 있다.


함수 호이스팅

//함수 호출
console.log(add(2, 5)); //7
console.log(sub(2, 5)); //TypeError: sub is not a function

// 함수 선언문
function add(x, y) {
  return x + y;
}

// 함수 표현식
var sub = function (x, y) {
  return x = y;
}

위의 예제를 확인하면 함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출할 수 있다. 이처럼 함수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 특징을 함수 호이스팅이라 한다.

하지만 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다. 따라서 함수 표현식으로 정희한 함수는 반드시 함수 표현식 이후에 참조 또는 호출해야 한다.

이렇게 보면 함수 선언문은 호출 전에 선언이 먼저 되어야 한다는 당연한 결과를 무시하게 된다. 그래서 JSON의 창시자 더글라스 크락포드는 함수 선언문 대신 함수 표현식을 사용할 것을 권장한다.

profile
노션 및 티스토리로 이동 예정입니다.

0개의 댓글