본문으로 바로가기

호이스팅(hoisting): 분산된 var 선언의 문제점

자바스크립트에서는 함수 내 여기저기서 여러 개의 var 선언을 사용할 수 있지만, 실제로는 모두 함수 상단에서 변수가 선언된 것과 동일하게 동작하게 됩니다.

이러한 동작 방식을 '호이스팅(hoisting, 끌어올리기)'이라고 합니다.

때문에 함수 안에서 변수를 사용한 다음에 선언하면 로직상의 로직상의 오류를 일으킬 수 있습니다.

자바스크립트는 동일한 유효범위(즉, 동일한 함수) 안에 있는 변수는 var 선언 전에 사용해도 이미 선언된 것으로 간주합니다.




다음의 예제를 살펴보도록 합니다.

javascript
// 안티 패턴
name = 'global'; // 전역 변수
function func() {
    console.log(name); // 'undefined' 가 기록된다.
    var name = 'local';
    console.log(name); // 'local' 이 기록된다.
}
func();

이 예제를 보면 첫 번째 콘솔의 결과로 'global' 가 출력되고 두 번째에는 'local'이 출력될 것이라고 예상하기 쉽습니다.

첫 번째 콘솔이 출력되는 시점에는 name 이 아직 선언되지 않았으므로 전역 변수인 name 을 바라볼 것이라고 예상해야 맞을 것 같습니다.

그러나 실제 동작은 그렇지 않습니다.

첫 번째 콘솔은 undefined 를 출력하게 됩니다.

name 이 이 함수의 지역 변수로 선언되었다고 간주하기 때문입니다.

선언문 자체는 그 다음에 나온다 하더라도 말입니다.

모든 변수 선언문은 함수 상단으로 끌어올려지게 됩니다.

따라서 이러한 혼란을 피하기 위해서는 사용할 변수를 모두 맨 첫 줄에서 선언하는 것을 권장합니다.



앞의 코드를 다음과 같이 작성한 것과 동일하게 동작합니다.

javascript
name = 'global';
function func() {
    var name; // 이렇게 변수 선언문을 작성하면 var name = undefined; 라고 쓴 것과 동일한 것이다.
    console.log(name); // 'undefined' 가 기록된다.
    name = 'local';
    console.log(name); // 'local' 이 기록된다.
}
func();



Conclusion

실제 구현 단계는 좀 더 복잡하다는 사실을 알아야 합니다.

코드는 두 단계를 거쳐 처리하게 됩니다.

첫 번재 단계에서는 변수, 함수 선언, 형식 매개변수들이 생성되며 코드를 파싱하고 실행 문맥으로 들어갑니다.

두 번째 단계는 런타임 코드 실행 단계로, 함수 표현식과 지정되지 않은 식별자(선언되지 않은 변수)들이 생성됩니다.

그러나 실무에서는 호이스팅 개념을 사용해도 무리가 없을 것입니다.

이 개념은 사실 ECMAScript 표준안에 정의되진 않았지만 코드의 동작 방식을 설명하는 데 널리 사용되고 있습니다.



Jaehee's WebClub