본문 바로가기

Javascript

[JavaScript] 호이스팅, Hoisting

반응형

 

하나의 스코프 안에서 선언된 변수는 바로 그 스코프에 속하고

마찬가지로 하나의 블록 안에서 선언된 변수는 바로 그 블록에 속하게 된다.

 

하지만,

선언문이 스코프의 어디에 있는지에 따라 스코프에 변수가 추가되는 과정이 미묘한 차이가 있다.

 

예시 )

/*
 * 스코프 위에 선언된 변수인 경우
 */
a = 2;
var a;
console.log(a); // 2

/*
 * 스코프 아래에 선언된 변수인 경우
 */
console.log(b); // undefined
var b = 2; 

 

위의 예시를 설명하기에 앞서 자바스크립트 컴파일러를 돌아볼 필요가 있다.

자바스크립트 엔진이 코드를 인터프리팅하기 전에 컴파일 한다는 사실을 기억해보자.

컴파일레이션 단계 중에는 모든 선언문을 찾아 적절한 스코프에 연결해주는 과정이 있었다. 이를 바로 렉시컬 스코프의 핵심이라 했다.

 

그러면 변수와 함수 선언문 모두 코드가 실제 실행되기 전에 먼저 처리된다고 보면된다.

따라서 자바스크립트는  "var a=2;" 를 다음 두개의 구문으로 본다.

  • var a;
  • a = 2;

 

그러므로 위의 예제를 다시 컴파일러 시점으로 본다면 아래와 같이 실행된다.

 

/*
 * 스코프 위에 선언된 변수인 경우
 */
var a;
a = 2;
console.log(a); // 2

/*
 * 스코프 아래에 선언된 변수인 경우
 */
var b;
console.log(b); // undefined
b = 2; 

 

이 과정을 변수와 함수 선언문은 선언된 위치에서 코드의 꼭대기로 '끌여올려진다'고 해서, 호이스팅(Hoisting) 이라 한다.

 

 참고 1 

만약 "중복"된 함수와 변수 선언문이 함께 있다면, 먼저 함수가 끌어올려지고 다음으로 변수가 올려진다.

 

예시 )

test(); // 1
var test;

function test() {
	console.log(1);
}

test = function() {
	console.log(2);
}

 

위의 예제를 다시 컴파일러 시점으로 본다면 아래와 같이 중복된 변수는 무시된채 실행된다.

 

function test() {
	console.log(1);
}

test(); // 1

test = function() {
	console.log(2);
}

 

따라서 스코프 내 중복정의가 얼마나 혼란스러운 결과를 나타내는지 알 수 있다.

변수와 함수는 중복된 명칭으로 정의하지 말자 !!

 

 참고 2 

일반 블록 안에서 보이는 함수 선언문은 보통 둘러싼 스코프로 끌러올려주지만, 이를 따르지 않을 수도 있다.

블록 내 함수 선언은 지양하자 !!

 

예시 )

test(); // Uncaught TypeError: test is not a function

var t = true;
if (t) {
	function test() {
    	console.log("a");
    }
} else {
	function test() {
    	console.log("b");
    }
}

 


[참고] You Don't Know JS 타입과 문법, 스코프와 클로저 - 카일 심슨

 

반응형

❥ CHATI Github