호이스팅 - (JavaScript)

Jiwonp·2023년 2월 23일
1

JavaScript 정리

목록 보기
1/6
post-thumbnail

2023.02.23

호이스팅

JavaScript에서 호이스팅 이란 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미한다.

코드가 실행하기전 변수선언/함수선언을 해당 스코프의 최상단으로 끌어올리는 것이 아닌, 해당 스코프의 최상단으로 끌어 올려진것 같은 현상을 말한다.

var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화 한다.
반면 letconst로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않는다.


예제 (코어 자바스크립트)

 function a (x) {   // 수집 대상 1(매개변수)
	console.log(x); // (1)
    var x;   		// 수집 대상 2(변수선언)
    console.log(x)  // (2)
    var x = 2;		// 수집 대상 3(변수선언)
    console.log(x)	// (3)
}
a(1)

우선 호이스팅이 되지 않았을 때 (1), (2), (3)에서 어떤 값들이 출력될지를 예상해 봅시다. 필자의 생각에는 (1)에는 함수 호출 시 전달한 1이 출력되고, (2)는 선언된 변수 x에 할당한 값이 없으므로 undefined가 출력되고, (3)에서는 2가 출력될 것 같습니다. 실제로는 어떤 결과가 나오고 왜 그렇게 되는지 알아봅시다.
(예상 : 1, undefined, 2)

주의
지금부터는 자바스크립트 엔진의 구동 방식을 좀 더 사람의 입장에서 이해해보고자 코드를 몇 차례 변경할 것입니다. 실제 엔진은 이러한 변환 과정을 거치지 않습니다.

매개변수를 변수 선언/할당과 같다고 간주해서 변환한 상태

fuction a () {
	var x = 1;		// 수집 대상 1(매개변수 선언)
    console.log(x); // (1)
    var x;			// 수집 대상 2(변수 선언)
    console.log(x); // (2)
    var x = 2;		// 수집 대상 3(변수 선언)
    console.log(x); // (3)
}
a();

이 상태에서 변수 정보를 수집하는 과정, 즉 호이스팅을 처리해 봅시다.
EnvironmentRecord는 현재 실행될 컨텍스트의 대상 코드 내에 어떤 식별자들이 있는지에만 관심이 있고, 각 식별자에 어떤 값이 할당될 것인지는 관심이 없습니다. 따라서 변수를 호이스팅할때 변수명만 끌어올리고 할당 과정은 원래 자리에 그대로 남겨둡니다. 매개변수의 경우도 마찬가지입니다. EnvironmentRecord의 관심사에 맞춰 수집 대상 1, 2, 3을 순서대로 끌어 올리고 나면 다음과 같은 형태로 바뀝니다.

호이스팅을 마친 상태

function a () {
02	var x;			// 수집 대상 1의 변수 선언 부분
03  var x;			// 수집 대상 2의 변수 선언 부분
04  var x;			// 수집 대상 3의 변수 선언 부분
    
06  x = 1;			// 수집 대상 1의 할당 부분
07  console.log(x); // (1)
08  console.log(x); // (2)
09  x = 2;			// 수집 대상 3의 할당 부분
10  console.log(x); // (3)
}
a(1);

설명

이제 호이스팅이 끝났으니 실제 코드를 진행할 차례입니다.

  • 2번째 줄: 변수 x를 선언합니다. 이때 메모리에서는 저장할 공간을 미리 확보하고, 확보한 공간의 주솟값을 변수 x에 연결해둡니다.

  • 3번째 줄과 4번째 줄: 다시 변수x를 선언합니다. 이미 선언된 변수 x가 있으므로 무시합니다.

  • 6번째 줄: x에 1을 할당하라고 합니다. 우선 숫자 1을 별도의 메모리에 담고, x와 연결된 메모리 공간에 숫자 1을 가리키는 주솟값을 입력합니다.

  • 7번째 줄과 8번째 줄: 각 x를 출력하라고 합니다. (1) (2) 모두 1이 출력됩니다.

  • 9번째 줄: x에 2를 할당하라고 합니다. 숫자 2를 별도의 메모리에 담고, 그 주솟값을 든 채로 x와 연결된 메모리 공간으로 갑니다. 여기에는 숫자 1을 가리키는 주솟값이 들어있었는데, 이걸 2의 주솟값으로 대치합니다. 이제 변수 x는 숫자 2를 가리키게 됩니다.

  • 10번째 줄: x를 출력하라고 하니 (3)에서는 2가 출력되고, 이제 함수 내부의 모든 코드가 실행됐으므로 실행 컨텍스트가 콜 스택에서 제거됩니다.

정답

처음 예상 (1) 1, (2) undefined, (3) 2로 출력되리라 예상했는데, 실제로는
(1) 1, (2) 1, (3) 2
라는 결과가 나왔습니다. (2)에서 undefined가 아닌 1이 출력된다는 건 호이스팅 개념을 정확히 이해하지 못하면 예측하기 어려운 결과죠.


추가

01 function a () {
02		console.log(b);		// (1)
03		var b = 'bbb';		// 수집 대상 1(변수 선언)
04		console.log(b);		// (2)
05		function b () {}	// 수집 대상 2(함수 선언)
06		console.log(b);		// (3)
07 }
08 a();

(1), (2), (3) 에선 과연 뭐가 출력이 될지 맞춰보자 😊







정답2

01 function a () {
02		var b;
03		var b = function b () {}
04		
05		console.log(b);		// (1)
06		b = 'bbb'	   		
07 		console.log(b);		// (2)
08		console.log(b);		// (3)
09 }
10 a();

정답은 (1) b 함수, (2) 'bbb', (3) 'bbb' 입니다👍
만약 (1) 에러 또는 undefined, (2) 'bbb', (3) b함수가 나올거라 생각했거나 틀렸다면 1번 문제부터 다시 풀어보도록 하자!

profile
매일 풀타임 코딩

1개의 댓글

comment-user-thumbnail
2023년 2월 23일

문제2 (1) undefined로 예상했습니다 .. 코어자바스크립트 찾으러 갑니다 🏃🏻‍♀️🏃🏻‍♀️

답글 달기