함수 리터럴(2)
이 글은 필자의 함수 리터럴 다음 애기이다. 함수의 동작원리에 대해 알고 있다면 상관없지만 그렇지 않다면
이 전 글을 보고 오는걸 권장한다.
함수 표현식
저번 글에서도 말했듯이 자바 스크립트의 함수는 값처럼 변수에 할당할 수도 있고 프로퍼티 값이 될 수도
있으며 배열의 요소가 될 수도 있다.
이처럼 값의 성질을 갖는 객체를 일급객체라 한다.
함수 리터럴의 함수 이름은 생략할 수 있다. 이러한 함수를 익명 함수라 한다.
함수 표현식의 함수 리터럴은 함수 이름을 생략하는 것이 일반적이다.
함수 선언문에서 이 전 글에서 본 바와 같이 함수를 호출할 때는 이름이 아니라
함수 객체를 가리키는 식별자를 사용해야 한다.
함수 이름은 함수 몸체 내부에서만 유효한 식별자이므로 함수 이름은 함수를 호출할 수 없다.
자바스크립트 엔진은 함수 선언문의 함수 이름으로 식별자를 암묵적 생성하고 생성된 함수 객체를 할당하므로
함수 표현식과 유사하게 동작하는 것처럼 보인다.
하지만 함수 선언문과 함수 표현식이 정확히 동일하게 동작하지는 않는다.
함수 선언문은 "표현식이 아닌문"이고 함수 표현식은 "표현식인 문"이다.
따라서 미묘하지만 중요한 차이가 있다.
함수 생성 시점과 함수 호이스팅
위 사진과 같이 함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출할 수 있다.
그러나 함수 표현식으로 정의한 함수는 표현식 이전에 호출할 수 없다.
이는 함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성 시점이 다르기 때문이다.
모든 선언문이 그렇듯 함수 선언문도 코드가 한 줄씩 순차적으로 실행되는 시점인 런타임 이전에 자바스크립트
엔진에 의해 먼저 실행된다. 다시 말해 함수 선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성된다.
그리고 자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 생성된 함수 객체를 할당한다.
즉, 코드가 한 줄씩 순차적으로 실행되기 시작하는 런타임에는 이미 함수 객체가 생성되어 있고 함수 이름과 동일한
식별자에 할당까지 완료된 상태이다. 따라서 함수 선언문 이전에 함수를 참조할 수 있으며 호출할 수도 있다.
이 처럼 함수 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는 자바스크립트 고유의 특징을 함수 호이스팅 이라 한다
함수 호이스팅과 변수 호이 스팅은 미묘한 차이가 있으므로 주의해야 한다.
var 키워드를 사용한 변수 선언문과 함수 선언문은 런타임 이전에 자바스크립트 엔진에 의해 먼저 실행되어 식별자를
생성한다는 점에서 동일하다. 하지만 var 키워드로 선언된 변수는 undefined로 초기화되고, 함수 선언문을 통해
암묵적으로 생성된 식별자는 함수 객체로 초기화된다. 따라서 var 키워드를 사용한 변수 선언문 이전에 변수를 참조하면
변수 호이스팅에 의해 undedfined로 평가되지만 함수 선언문으로 정의한 함수를 함수 선언문 이전에 호출하면
함수 호이스팅에 의해 호출이 가능하다
함수 표현식은 변수에 할당되는 값이 함수 리터럴인 문이다. 따라서 함수 표현식은 변수 선언문과 변수 할당 문을
한 번에 기술한 축약 표현과 동일하게 동작한다.
변수 선언은 런타임 이전에 실행되어 undefined로 초기화되지만
변수 할당 문의 값은 할당 문이 실행되는 시점, 즉 런타임에 평가되므로 함수 표현식의 함수 리터럴도 할당문이
실행되는 시점에 평가되어 함수 객체가 된다.
따라서 함수 표현식으로 함수를 정의하면 함수 호이 스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다.
출처
책: 모던 자바스크립트 Deep Dive