saewoo
githubemail
2021-9-23

함수 선언문과 함수 표현식의 호이스팅

호이스팅

호이스팅이란 코드가 한 줄씩 순차적으로 실행되지 않고 코드가 스코프 선두로 끌어 올려진 것처럼 동작하는 것입니다.

‘끌어 올려진 것처럼’이라고 표현한 이유는 실제로 스코프 선두로 올라가는 것은 아니기 때문입니다.

실행 컨텍스트가 콜스택에 푸시되기 이전에 실행 컨텍스트의 렉시컬 환경에서 식별자 정보를 수집하는데

콜스택에 푸시되어 런타임 시엔 식별자의 정보를 이미 알고 있으므로 끌어올려진 것처럼 보이는 것입니다.

함수 선언문

함수 선언문은 다른 문들과 마찬가지로 함수가 호이스팅되고,

실행 컨텍스트 생성시 함수 객체가 생성됩니다.

한 줄 한 줄 실행되는 런타임 시엔 변수에 대한 정보와 함수 객체가 이미 생성되어 있기 때문에

선언 이전에 호출이 가능한 것입니다.

add(1,2) // 3

function add(1,2) {
  return a + b;
}

함수 표현식

반면에 함수 표현식은 변수에 할당되는 값이 '함수 리터럴'이므로

문자 리터럴, 숫자 리터럴과 같이 함수 호이스팅이 아닌 변수가 호이스팅 됩니다.

add(1,2) // Uncaught TypeError: add is not a function

var add = function (a,b) {
  return a + b;
}

위와 같이 var 키워드 사용시 변수가 호이스팅되고,

런타임에서는 add 변수의 존재를 알지만,

아직 함수 리터럴의 할당이 이루어지기 전이므로

변수에는 초깃값 undefined가 할당되어 있어서

'add is not a function'이라는 에러 메시지가 뜨는 것을 볼 수 있습니다.


반면에 const 키워드, let 키워드를 쓰면 호이스팅 되는것은 동일하지만,

언어 차원에서 할당 이전엔 TDZ에 보내 할당 이전에 참조가 불가능하게 되어

'add is not defined' 에러가 발생하게 됩니다.

add(1,2) // Uncaught ReferenceError: add is not defined

const add = function (a,b) {
  return a + b;
}

정리

함수 선언문은 함수가 호이스팅. 런타임 이전에 함수 객체 생성

함수 리터럴은 변수가 호이스팅. 런타임에 함수 객체 생성