실행 컨텍스트 - 호이스팅, 스코프

이윤환·2022년 4월 5일
0
post-custom-banner

앞서 나온 코드를 살펴보며 호이스팅과 스코프를 설명하겠다.

// -- (1)
var a = 1;

function outer(){
	function inner(){
    	console.log(a); // undefined
      	var a = 3;
    }
  	inner(); // --(2)
  	console.log(a); // 1
}
outer(); // --(3)
console.log(a);  //1

위 코드가 의아하지 않은가? 난 의아했다.
5번째줄의 결과값이 왜 undefined 인가 이건 javascript의 호이스팅에 의한 결과다.

호이스팅

먼저 다른데에서 검색을 해본다면 호이스팅이란 'js 엔진이 식별자들을 최상단으로 끌어올려놓는 것' 이라고 나올거다.
js 에서는 변수등을 선언 할 경우 코드를 실행하기도 전에 변수들을 최상단에 올려놓음으로써 js 엔진은 코드의 변수명들을 이미 알고 있는 셈이 되는것이다.

실제로는 끌어올린것은 아니다.
변수명을 안다는 것은 즉 값이 아직 정해지지 않았다는 뜻이므로 undefined 라는 값이 된다.

즉 inner 함수가 선언되면서 a라는 값을 호이스팅을 하였으므로 5번째 줄에서 undefined가 출력이 된다.

앞서 작성한 실행 컨텍스트의 environmentRecord에는 매개 변수의 이름, 함수 선언, 변수명 등이 담긴다고 했다.

environmentRecord는 변수를 호이스팅 할 경우 값과 상관없이 선언 자체만을 상단으로 끌어올릴뿐이라 상관이 없다.

위 코드를 environmentRecord의 방식으로 호이스팅을 마쳤다고 가정하고 다시 재작성을 한다면

// -- (1)
var a = 1;

function outer(){
	function inner(){
      	var a; // 호이스팅
    	console.log(a); // undefined
      	a = 3; // 값 할당
    }
  	inner(); // --(2)
  	console.log(a); // 1
}
outer(); // --(3)
console.log(a);  //1

다른 예제를 한 번 더 살펴보자

function a(x){
    console.log(x); // 1
    var x;
    console.log(x); // 1
    var x = 2;
    console.log(x); // 2
}

a(1);

라는 코드를 다시 재해석해 보자면

function a(x){
  	var x;
  	var x;
  	var x;
  
  	x = 1;
    console.log(x);
    console.log(x);
    x = 2;
    console.log(x);
}

라는 방식으로 해석이 되므로 값이 1,1,2 순으로 출력이 된다.

이처럼 호이스팅은 '함수 내에서 선언된 식별자들의 변수명을 최상단으로 끌어 올린 것 같은 현상' 이라는 말 할 수 있겠다.

근데 아직도 의문이 있다.
최상단에서 선언한 a값은 왜 영향을 끼치지 않는지 궁금 할 수 있다.

그 이유는 스코프 라는 개념을 알아보면 된다.

스코프와 스코프 체인

스코프란 식별자에 대한 유효범위다.
외부에서 선언한 변수는 내부 함수에서 접근이 가능하지만 내부에서 선언한 변수는 외부에서 접근이 불가능하다.

식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해 나가는 것을 스코프 체인 이라고 한다.
그리고 이런 것을 가능하게끔 해주는 것이 outerEnvironmentReference이다.

가령 A라는 함수에서 B 함수를 선언하고 다시 B 함수에서 C 라는 함수를 선언한 경우 함수 C의 outerEnvironmentReference에서는 함수 B의 LexicalEnvironment를 참조한다.
함수 B의 outerEnvironmentReference 또한 A의 LexicalEnvironment를 참조한다.
이처럼 outerEnvironmentReference는 안에서 바깥으로 끝내는 전역 컨텍스트의 LexicalEnvironment까지 참조하는 형태의 연결 리스트 형태를 띄운다.

이런 구조때문에 여러 스코프내에서 동일한 식별자를 선언한 경우 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근이 가능하다.

즉 최상단의 코드에서 전역 컨텍스트에 a라는 식별자가 있지만 inner 함수에서 a라는 식별자가 존재하므로 inner 함수의 a의 값(호이스팅으로 값이 할당 되기 전에 출력 됐으므로 undefined)을 출력하게 되는 것이다.

정리

  • 호이스팅은 함수 내에 선언된 변수명을 최상단에 끌어올리는 것
  • 스코프는 식별자의 유효 범위
  • 스코프 체인은 식별자의 유효범위를 안에서부터 바깥으로 찾는 것
profile
나는 이윤환
post-custom-banner

0개의 댓글