# 함수 생성 시점과 함수 호이스팅
// 함수 참조
console.dir(add); // ƒ add(x, y)
console.dir(sub); // undefined
// 함수 호출
console.log(add(2, 5)); // 7
console.log(sub(2, 5)); // Uncaught TypeError: sub is not a function
// 함수 선언문
function add(x, y) {
return x + y;
}
// 함수 표현식
var sub = function (x, y) {
return x + y;
}
함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출할 수 있다.
함수 표현식으로 정의한 함수는 함수 표현식 이전에 호출할 수 없다.
=> 함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성 시점이 다르기 때문이다.
모든 선언문이 그런 것 처럼 함수 선언문도 코드가 한 줄씩 순차적으로 실행되는 시점인 런타임(runtime) 이전에 자바스크립트 엔진에 의해 먼저 실행된다. 즉, 함수 선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성 된다.
코드가 한 줄씩 순차적으로 실행되기 시작하는 런타임에는 이미 함수 객체가 생성되어 있고 함수 이름과 동일한 식별자에 할당까지 완료된 상태다. 따라서 함수 선언문 이전에 함수를 참조할 수 있고 호출할 수도 있다.
이처럼 함수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 함수 호이스팅(function hoisting)이라 한다.
※ 함수 호이스팅은 변수 호이스팅과 다르다.
var 키워드를 사용한 변수 선언문과 함수 선언문은 런타임 이전에 자바스크립트 엔진에 의해 먼저 실행되어 식별자를 생성한다는 점에서 동일하다.
하지만 var 키워드로 선언된 변수는 undefined로 초기화되고, 함수 선언문을 통해 암묵적으로 생성된 식별자는 함수 객체로 초기화 된다. 따라서 변수 선언문 이전에 변수를 참조하면 undefined로 평가되지만 함수 선언문 이전에 함수를 호출하면 함수 호이스팅에 의해 호출이 가능하다.
함수 표현식은 변수아 할당되는 값이 함수 리터럴인 문이다.
'함수 표현식 = 변수 선언문 + 변수 할당문' 인 셈이다.
변수 선언은 런타임 이전에 실행되어 undefined로 초기화되지만 변수 할당문의 값은 할당문이 실행되는 시점, 즉 런타임에 평가 되므로 함수 표현식의 함수 리터럴문도 할당문이 실행되는 시점에 평가되어 함수 객체가 된다.
따라서 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다.
함수 표현식 이전에 함수를 참조하면 undefined로 평가된다. 따라서 함수를 호출하면 undefined를 호출하는 것과 마찬가지이므로 타입 에러가 발생한다.
함수 표현식으로 정의한 함수는 반드시 함수 표현식 이후에 참조 또는 호출해야한다.
함수 호이스팅은 함수를 호출하기 전에 반드시 함수를 선언해야 한다는 당연한 규칙을 무시하므로 JSON을 창안한 더글라스 크락포드는 함수 선언문 대신 함수 표현식을 사용할 것을 권장한다.
퀴즈
- 모든 선언문이 그런 것 처럼 함수 선언문도 코드가 한 줄씩 순차적으로 실행되는 시점인 ( ) 이전에 자바스크립트 엔진에 의해 먼저 실행된다. 즉, 함수 선언문으로 함수를 정의하면 ( ) 이전에 함수 객체가 먼저 생성 된다.
정답: 런타임(runtime)
- 함수 호이스팅과 변수 호이스팅의 차이점은?
정답: var 키워드로 선언된 변수는 undefined로 초기화되고, 함수 선언문을 통해 암묵적으로 생성된 식별자는 함수 객체로 초기화 된다. 따라서 변수 선언문 이전에 변수를 참조하면 undefined로 평가되고 함수 선언문 이전에 함수를 호출하면 함수 호이스팅에 함수 호출이 가능하다.
- 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생한다(O,X)
정답: X
풀이: 함수 표현식으로 함수를 정의하면 변수 호이스팅이 발생한다.
함수 표현식은 변수 선언문과 변수 할당문으로 이루어져있기 때문에 변수 선언은 런타임 이전에 실행되어 undefined로 초기화 되지만, 변수 할당문의 값은 런타임에 평가되므로 함수 표현식의 함수 리터럴문은 할당문이 실행되는 시점에 평가되어 함수 객체가 된다.
- 함수 표현식 이전에 함수를 참조하면?
정답: 타입 에러가 발생한다.
함수 표현식 이전에 함수를 참조하면 undefined로 평가된다. 따라서 함수를 호출하면 undefined를 호출하는 것과 마찬가지이므로 타입 에러가 발생한다.
'JavaScript' 카테고리의 다른 글
[JavaScript] 함수 - 참조에 의한 전달과 외부 상태의 변경 (2) | 2023.10.27 |
---|---|
[JavaScript] 함수 - 함수 호출 (2) | 2023.10.27 |
[JavaScript] 함수 - Funtion 생성자 함수, 화살표 함수(개념만) (0) | 2023.10.27 |
[JavaScript] 함수 - 함수를 사용하는 이유, 함수 리터럴, 함수 정의 (0) | 2023.10.23 |
[JavaScript] 프로퍼티 어트리뷰트 (0) | 2023.10.20 |