[JavaScript] 호이스팅 이란?
호이스팅(Hoisting)이란?
자바스크립트 Parser가 함수를 실행하기 전 함수를 한번 훑는다.
여기서, 함수 안에 필요한 변수 값들을 모두 모아서 유효 범위의 최상단에 선언 하는데, 이를 호이스팅(Hoisting)이라 한다
함수 안 (블록 안 { }) 에서만 유효하고, 실제로 코드가 끌어올려 지는 것이 아니라 자바스크립트 Parser 내부적으로 끌어올려 처리하는 것이다. 때문에 실제 메모리에는 어떠한 변화도 발생하지 않는다.
호이스팅의 대상
1. var 변수 선언
변수 선언의 경우 var에서만 호이스팅이 일어난다. let / const 변수 선언에서는 호이스팅이 발생하지 않는다.
여기서 변수의 선언만 끌어올려지고, 할당은 함께 끌어올려지지 않는다.
console.log(hello); // undefined 정상 출력
console.log(world); // 오류
console.log(nice); // 오류
var hello = "Hello,"; // var 변수
let world = "World"; // let 변수
const nice = "Nice to Meet You!"; // const 변수
2. 함수 선언문
함수 선언문에서만 호이스팅이 일어나고, 함수 표현식에서는 호이스팅이 일어나지 않는다.
hello(); // 정상 동작
world(); // 오류
nice(); // 오류
function hello() { // 함수선언문
console.log("Hello");
}
var world = function() { // 함수 표현식
console.log("World");
}
var nice = () => { // 함수 표현식 (화살표 함수)
console.log("Nice to Meet You!");
}
그도 그럴것이, 변수의 경우에도 선언만 끌어올려지고 할당은 끌어올려 지지 않기 때문에 아래의 코드를 보면
함수를 할당 하기전에 world의 경우 함수가 아닌 undefined의 값을 가진 변수다.
함수를 호출하는 것 대신 각 함수를 호출해보면 이해가 더 쉬울 것이다.
console.log(hello); // 정상 출력 [Function: hello]
console.log(world); // 정상 출력 undefined
console.log(nice); // 오류
hello(); // 함수 작동
world(); // Type Error (world는 undefined임)
nice(); // Reference Error (nice는 const라 호이스팅이 되지 않음)
function hello() { // 함수선언문
console.log("Hello");
}
var world = function() { // 함수 표현식
console.log("World");
}
const nice = () => { // 함수 표현식 (화살표 함수)
console.log("Nice to Meet You!");
}
위의 결과를 보면, hello는 함수로 호이스팅이 된 상태고, world는 호이스팅으로 변수 선언은 되었지만 값(함수)이 할당되지 않았다. 그리고 nice 는 const 변수에 함수를 할당 했기 때문에 호이스팅 자체가 되지 않아 오류를 발생 시킨다.
호이스팅 우선순위
var hello = 'Hello';
function hello() {};
console.log(typeof hello); // string
위 코드를 실행하면 world가 function이 아니라 string이다..! function이 아니라 왜 string이 되는 걸까?
변수 선언이 함수 선언보다 더 위로 끌어 올려지기 때문이다. 이해가 잘 안된다면, 아래 코드를 보자. 호이스팅이 일어난 후에 코드는 다음과 같다고 볼 수 있다.
var hello; // hello 변수 호이스팅
function hello() {}; // 함수 선언문 호이스팅
hello = 'Hello'; // hello에 string 할당
console.log(typeof hello); // string
hello의 변수에 값을 할당 시키지 않는다면 마지막으로 hello는 함수 선언문으로 저장이 되었기 때문에, 타입으로 함수를 출력하게 될 것이다.
function hello() {}; // hello 변수 선언 다음으로 끌어 올려짐
var hello; // 제일 위로 끌어 올려 짐
console.log(typeof hello); // function
주의할 점
호이스팅이 일어나는 코드는 가독성이 떨어져 유지보수를 하기도 힘들어진다. 때문에 변수나 함수 선언은 가능한 함수의 최 상단부에 위치 시키는 것이 좋다. 뿐만아니라 변수를 사용 할 때에는 var 보다는 let, const를 사용하는 것이 좋다. (호이스팅도 방지하고, 변수명을 중복으로 사용할 수 없게 해서 코드를 좀더 안정적으로 작성할 수 있기도 하다.)
하지만 let, const는 ES6부터 사용가능 한 문법이고 웹 호환성을 위해서는 트랜스파일러를 사용해 모든 변수 타입은 var로 변경이 된다. 때문에 호이스팅이 어떻게 일어 나는지, 왜 일어나는지 이해를 할 필요가 있다.
참고
https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html