본문 바로가기
Javascript

자바스크립트 호이스팅 (JavaScript hoisting)

by ttum 2020. 3. 20.

이전에 함수 호이스팅에 관해 공부를 하 난 후에 정리하면서 쓴 이 있다. 

그러나 최근에 다시 호이스팅에 대해 공부를 하게 되면서 조금 더 알게 된 내용이 있어 정리하게 됐다.

 

호이스팅이라는 것은 "끌어올린다"는 뜻이다.

console.log(one);
console.log(two());

var one = 1;
function two(){
	return 2;
}

위의 코드를 실행시키면 각각 undefined2가 결과로 나타난다.

C++과 같이 호이스팅이 일어나지 않는 언어를 사용한다면 undefined나 결과가 나올 것이 아니라 정의되지 않는 변수 또는 함수라고 나와야 정상이지만 왜 자바스크립트에서는 이런 결과가 나오는 것인지에 대해 알아보자.

 

그렇다면 언제, 무엇을 끌어올린다는 것일까?

자바스크립트 컴파일 과정에서 varfunction이라는 키워드를 발견하면 이것은 가장 위로 끌어올려진다.

그리고 미리 메모리 힙 영역을 차지한다.

console.log(one);
console.log(two());

var one = 1;
function two(){
	return 2;
}

그렇기 때문에 이 코드에서도 one이라는 변수와 two라는 함수가 가장 위로 끌어올려졌고, 위의 로그 출력시에 undefined와 2라는 결과가 나타나게 된 것이다.

 

여기서 재미있는 것은 var와 function이라는 키워드가 문장 맨 앞에 있을 때 호이스팅이 발생한다는 것이다.

가령 아래와 같이 함수가 괄호로 쌓여져있는 경우에는 호이스팅이 일어나지 않는다.

console.log(one);
console.log(two());

var one = 1;
(function two(){
	return 2;
});

console.log(two())에 대한 결과는 two가 정의되지 않는 함수라고 나온다.

 

한 가지 예시만 더 확인하고 호이스팅이 어떻게 동작하는 지에 대해 다뤄보자.

console.log(one);
console.log(two);

var one = 1;
var two = function(){
	return 2;
};

이 코드의 결과는 undefined, undefined이다.

(var two에서 사용된 function 키워드는 문장 맨 앞에서 사용된 것이 아니므로 함수 전체가 호이스팅 되는 일은 발생하지 않았다. 하지만 two라는 변수는 호이스팅 되었다. 이해가 잘 가지 않는다면 다음에 이어서 설명할 내용이니 계속 읽으면 된다 :) )

 

호이스팅은 어떻게 이루어지는 것일까?

이를 다루기 전에 먼저 호이스팅은 해당 실행 컨텍스트 안에서만 발생하는 것이라는 것을 알아두자.

이는 후에 다시 설명하도록 하겠다.

 

호이스팅은 말 그대로 코드를 끌어올린다.

console.log(one);
console.log(two);

var one = 1;
var two = function() {
	return 2;
};

위 코드의 컴파일 과정에서 var변수인 one과 two가 호이스팅의 대상이라는 것에는 이제 동의할 것이다.

one과 two가 호이스팅 된 결과는 아래와 같다.

var one = undefined;
var two = undefined;

console.log(one);
console.log(two);

one = 1;
two = function() {
	return 2;
};

var one과 var two가 가장 위로 끌어올려졌다. 이제 console.log의 결과가 둘다 undefined가 나타나는 것이 이해가 갈 것이다. function키워드의 경우는 함수 그대로 끌어올려진다고 생각하면 된다. 

 

이제 호이스팅이 언제, 어떻게 발생하는 지에 대해서는 이해가 갔을 것이다.

그렇다면 아래 코드에 대한 결과가 어떨지 고민해보자. 

var food = "grape";

var foodThought = function() {
  console.log("original favorite food: " + food);

  var food = "apple";

  console.log("new favorite food: " + food);
};

foodThought();

이 예시는 함수 안에 var 키워드가 선언되어있다.

우리는 지금까지 Global한 컨텍스트 안에서 코드가 실행되는 것만 살펴보았다.

(그렇지만 위에서 호이스팅이 해당 실행 컨텍스트 안에서 발생되는 것이라고 이미 힌트를 줬다)

 

말 그대로 실행컨텍스트 안에서 호이스팅이 일어난다고 보면 된다.

호이스팅의 결과는 아래와 같다.

var food = undefined;
var foodThought = undefined;

food = "grape";

foodThought = function() {
  var food = undefined;
  
  console.log("original favorite food: " + food);

  food = "apple";

  console.log("new favorite food: " + food);
};

foodThought();

 

결과는 예상할 수 있듯이 아래와 같다.

original favorite food: undefined

new favorite food: apple

 

어떻게 해결할까?

코드를 작성할 때에는 "예측 가능한" 코드를 작성하는 것이 좋다. 그런 의미에서 호이스팅은 예측하기 어렵게 만드는 요인이기 때문에 사용을 피하는 것이 좋다.

 

해결 하는 방법은 꽤 간단하다. 호이스팅을 발생시키는 조건인 var와 function키워드를 문장 가장 앞에 쓰는 것을 피하면 된다.

따라서 var를 사용하는 대신 ES6에서 새로 등장한 키워드인 const나 let키워드를 사용할 수도 있을 것이다.

그리고 함수를 선언할 때에도 함수 선언문 대신 함수 표현식을 사용하면 된다.

(물론 표현식을 사용할 때 또다시 var키워드를 사용한다면 또 다시 호이스팅이 일어날 것이다)

 

 

끝-!