[JavaScript]호이스팅(hoisting)이란 무엇일까?

C 같은 프로그래밍 언어에서 블록 안에 있는 코드는 자신만의 유효범위를 가지며, 변수는 해당 변수가 선언되지 않은 블록 밖에서는 보이지 않는다. 이를 블록 유효범위(block scope)라 부르는데, 자바스크립트에는 블록 유효범위의 개념이 없다. 대신에 자바스크립트는 함수 유효범위를 사용한다. 변수는 해당 변수가 정의된 함수 안에서 보일 뿐 아니라, 그 함수 안에 중첩된 함수 안에서도 보인다.
다음 코드에서 변수 i, j, k는 다른 위치에 선언되지만 모두 같은 유효범위를 갖는다. 다시 말해, 세 변수는 모두 함수의 몸체 안에 정의되어 있다.

function test(o){
   let i = 0;							//i는 함수 전체에 걸쳐 정의된다.
   if(typeof 0 == "object"){
   		let j = 0;						//j는 블록뿐만 아니라 함수 전체에 걸쳐 정의된다.
          for(let k=0; k<10; k++){	//k는 반복문 외에도 함수 전체에 걸쳐 정의된다.
          console.log(k); 			//숫자 0부터 9까지 출력한다. 
       }
       console.log(k); 				//k는 여전히 정의되어 있다. 10을 출력한다.
    }
    console.log(j); 				//j는 정의되어 있고, 초기화되어 있지 않을 것이다.
}

자바스크립트의 함수 유효범위(function scope)는, 어떤 함수 안에서 선언된 모든 변수는 그 함수 전체에 걸쳐 유효하다는 의미다. 흥미롭게도, 이는 변수가 미처 선언되기 전에도 유효하다는 뜻이기도 하다. 이런 자바스크립트의 특징은 비공식적으로 호이스팅(hoisting)이라고 알려져 있다. 자바스크립트 코드는 함수 안에 있는 모든 변수를 함수 맨 꼭대기로 '끌어올린' 것처럼 동작한다. 다음 예제를 통해 살펴보자.

var scope = "global";
function f() {
	console.log(scope); 	//"global"이 아니라 "undefined"를 출력한다.
    let scope = "local" 	//여기서 초기화하지만, 정의는 다른 곳에서 이루어졌다.
    console.log(scope);     //"local"을 출력한다.
}

지역 변수를 선언하는 var문이 아직 실행되지 않았기 때문에 여러분은 이 함수의 1행이 "global"을 출력할 거라고 착각할 수 있다. 하지만, 함수 유효범위 규칙 때문에 실제로는 그렇지 않다. 지역 변수는 함수 전체에 걸쳐서 정의된다. 즉, 같은 이름의 전역 변수는 함수 전체에서 이 지역 변수에 의해 감춰진다. 지역 변수가 함수 전체에 걸쳐 정의되었더라도 var문이 실행되고 나서야 실제로 초기화 된다. 따라서 이 함수는 다음 코드와 같다. 그리고 변수 선언은 함수 맨 꼭대기로 '끌어올려(hoisted)'지고, 초기화는 원래대로 세 번째 줄 대입문이 처리하게 된다.

function f() {
	var scope;				//지역 변수는 함수 맨 꼭대기에서 선언한다.
    console.log(scope); 	//scope 변수는 존재하지만 아직 "undefined" 값이다.
    scope = "local";		//이제 scope 변수가 초기화되고 제대로 된 값이 있다.
    console.log(scope);		//여기서는 우리가 기대한 값이 들어 있다.
}

블록 유효범위를 가진 프로그래밍 언어에서 일반적으로 변수를 선언하는 좋은 프로그래밍 방법은, 가능한 한 그 변수가 사용되는 가장 가까운 곳에서 선언하는 것이다. 하지만 자바스크립트는 블록 유효범위를 가지고 있지 않기 때문에 어떤 개발자는 모든 변수를 변수가 사용되는 위치와 가까운 곳에 선언하지 않고 함수의 맨 꼭대기에 선언할지도 모른다. 그렇게 하면 변수의 진정한 유효범위가 소스 코드에 정확하게 반영될 것이다.

좋은 웹페이지 즐겨찾기