[JS] Hoisting
《 실행 컨텍스트 》에 이어 작성하는 글입니다.
▶ 호이스팅
호이스팅이란 선언된 변수나 함수 선언시 scope 내의 최상단으로 끌어올리는 것을 말한다. (레코드를 수집하는 과정이 호이스팅⭐)
- 아래 코드는 어떻게 출력될지 생각해보자
console.log(a);
var a = 10;
js 코드는 인터프리터에 의해 한 줄씩 순차적으로 코드를 실행한다. 따라서 변수 a를 선언하기 전에 a를 출력하려고 하기 때문에 참조 에러가 발생하지 않을까?
❓ 하지만 참조 에러가 발생하지 않고 undefined
가 출력된다! 왜 그럴까?
그 이유는 변수 선언이 런타임 전 단계에서 실행되기 때문이다!
이게 무슨 말이냐, 런타임은 프로그램이 실행되고 있는 동안의 동작을 말한다. 즉, 프로그램이 실행되기 전에 변수 선언이 이루어진다는 것이다!
❓ 어떻게 프로그램이 실행되기 전 변수 선언이 이루어질 수 있을까?
인터프리터 과정을 거치기 전 소스코드의 평가 과정을 거치기 때문이다.
- 소스코드 평가 과정이란 변수 선언을 포함한 모든 선언문(변수, 함수 선언문 등)을소스코드에서 찾아내 먼저 실행한다. 이 과정이 끝난 후 코드를 순차적으로 실행하는 인터프리터 과정을 거친다.
- 즉, js 엔진은 변수 선언이 소스 코드 어디에 있던 다른 코드보다 먼저 실행이 되기 때문에 변수 선언이 어디에 위치해있던 어디서든지 변수를 참조할 수 있는 것이다.
이처럼 코드 실행 전 변수나 함수를 찾아 스코프의 최상단으로 끌어올려주는 것을 호이스팅이라 말한다.
따라서 위 코드는 변수 a가 선언되기 전에 출력되었지만, 호이스팅으로 인해 변수 선언문이 스코프의 최상단으로 이동되기 때문에 에러가 발생하지 않고 undefined
가 출력된다.
▶ 호이스팅 규칙
- 매개변수 및 변수는 선언부를 호이스팅 한다.
- 적용 전
function a(x) {
console.log(x);
var x;
console.log(x);
var x = 2;
console.log(x);
}
a(1);
- 매개변수 적용
function a() {
var x = 1;
console.log(x); // 1
var x;
console.log(x); // undefind
var x = 2;
console.log(x); // 2
}
a(1);
- 호이스팅 적용
function a() {
var x;
var x;
var x;
x = 1;
console.log(x); // 1
console.log(x); // 1
x = 2;
console.log(x); // 2
}
a(1);
➡️ 실행 결과를 1 → undefined → 2
로 예상했지만, 실제로 1, 1, 2
라는 결과가 나왔다.
➡️ 이는 호이스팅이 적용되었기 때문!
- 함수 선언은 전체를 호이스팅한다.
- 적용 전
function a() {
console.log(b);
var b = "bbb";
console.log(b);
function b() {}
console.log(b);
}
a();
- 호이스팅 적용
function a() {
var b; // 변수 선언부 호이스팅
function b() {} // 함수 선언은 전체를 호이스팅
console.log(b); // [Function: b] 출력
b = "bbb"; // 변수의 할당부는 원래 자리에
console.log(b); // bbb 출력
console.log(b); // bbb 출력
}
a();
▶ 함수 선언문과 표현식의 호이스팅
- 함수 선언문과 표현식에 대한 자세한 내용은 《 함수 》을 참고하자.
함수 선언문
- function 키워드를 사용하여 함수를 선언하는 방식을 말한다.
- 함수 선언문은 함수의 최상위로 호이스팅된다. 따라서 함수가 선언되기 전에 호출할 수 있다.
console.log(add(3, 2)); // 5
function add(x, y) {
return x + y;
}
함수 표현식
- 변수에 함수를 할당하는 방식을 말한다.
- 함수 표현식은 변수 선언 이전에 호출하면 에러가 발생한다.
- 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다.
- 즉, 변수 부분만 호이스팅 되는 것이다.
console.log(result(3, 2)); // TypeError
var result = function (x, y) {
return x + y;
};
- 적용 전
console.log(sum(1, 2));
console.log(multiply(3, 4));
function sum(a, b) {
// 함수 선언문 sum
return a + b;
}
var multiply = function (a, b) {
// 함수 표현식 multiply
return a + b;
};
- 적용 후
// 함수 선언문은 전체를 hoisting
function sum(a, b) {
// 함수 선언문 sum
return a + b;
}
// 변수는 선언부만 hoisting
var multiply;
console.log(sum(1, 2));
console.log(multiply(3, 4));
multiply = function (a, b) {
// 변수의 할당부는 원래 자리
return a + b;
};
➡️ 협업을 많이하고 복잡한 코드일수록, 전역 공간에서 이루어지는 코드 협업일 수록, 함수 표현식을 활용해야 한다!!
댓글남기기