본문 바로가기
JavaScript

[코어 자바스크립트] 1.실행 컨텍스트와 스코프, 호이스팅

by imsoncod 2021. 6. 23.

1. 실행 컨텍스트

  • 실행 컨텍스트란 실행할 코드에 제공할 환경 정보들을 모아놓은 객체입니다.
  • 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고 이를 콜스택에 쌓아 올립니다.
  • 실행 컨텍스트는 전역공간이 생성될 때, 함수가 호출될 때 생성됩니다.

실행 컨텍스트와 콜 스택 예제

코드 실행시, 전역공간이 활성화되면서 전역 컨텍스트가 생성되고 함수 호출 순서대로 콜스택에 실행 컨텍스트가 쌓이는것을 확인할 수 있습니다.

실행 컨텍스트가 담고 있는 정보

  • Variable Environment
    • environmentRecord (snapshot) : 현재 컨텍스트 내의 식별자들에 대한 정보
    • outerEnvironmentReference (snapshot) : 외부 환경 정보
  • Lexical Environment
    • environmentRecord : 현재 컨텍스트 내의 식별자들에 대한 정보
    • outerEnvironmentReference : 외부 환경 정보
    • Variable Environment와 동일하지만 변경사항이 실시간으로 반영됨
  • Variable Environment에 정보를 먼저 담고, 이를 그대로 복사해서 Lexical Environment를 만들고 이후 Lexical Environment를 주로 사용합니다.
  • ThisBinding : 식별자가 바라봐야 할 대상 객체

environmentRecord

매개변수명, 선언된 함수 자체, 변수명 등이 담깁니다.
컨텍스트 내부를 처음부터 까지 탐색하며 순서대로 수집합니다.

2. 호이스팅

  • 호이스팅은 식별자들은 최상단으로 끌어올리는 것을 뜻합니다.
  • 식별자만 끌어올리고 할당 과정은 그대로 남겨둡니다.
  • 편의상 끌어올리는 것으로 간주하는 가상의 개념이며 실제로 끌어올리지는 않습니다.
  • 이 과정을 마치면 코드 실행 전에도 자바스크립트 엔진은 변수명들을 모두 알고 있게 됩니다.

함수 선언문과 함수 표현식

  • 함수 선언문: function a () { /* ... */ }
  • 함수 표현식: var b = function () { /* ... */ }

큰 차이가 없어보이지만 호이스팅시 결과가 완전히 달라집니다.
때문에 함수 선언문으로 작성된 함수는 실행위치보다 아래에 있어도 원활하게 실행이 되지만 함수 표현식으로 작성된 함수는 XXX is not a function 에러를 출력합니다.

따라서 상대적으로 함수 표현식을 사용하는 것이 안전합니다.

함수 선언문의 경우 내부 코드까지 전체를 호이스팅하지만 함수 표현식의 경우 할당의 과정은 그대로 두고 선언부만 호이스팅합니다.

3. 스코프

  • 스코프란 식별자에 대한 유효범위입니다.
  • 변수를 어느 위치에 선언하느냐에 따라 변수를 사용할 수 있는 유효범위, 즉 스코프가 달라집니다.
  • 식별자의 유효성을 검사하기 위해 안에서부터 바깥으로 유효범위를 탐색해가는 것을 스코프 체인이라고 합니다.
    이 기능을 가능하게 해주는 것이 Lexical Environment의 두 번째 수집 자료인 outerEnvironmentReference입니다.

스코프 체인 과정

  • Lexical EnvironmentouterEnvironmentReference는 호출된 함수가 선언될 당시Lexical Environment를 참조합니다.

  • A함수 내부에 B를, B함수 내부에 C함수를 선언할 경우 아래와 같은 단방향 연결리스트의 형태로 참조합니다.

    C : outerEnvironmentReference —> B : Lexical Environment
    B : outerEnvironmentReference —> A : Lexical Environment

    따라서 가장 가까운 요소부터 차례로 접근하기 때문에 여러 스코프에서 동일한 식별자를 선언할 경우 스코프 체인상에서 가장 먼저 발견된 식별자에만 접근이 가능합니다.

  • 이후에 발견될 식별자에는 접근할 수 없으며 이를 변수 은닉화라고 합니다.

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

  inner();   
  console.log(a); // - (2) 
}

outer(); 
console.log(a); // --- (3) 

inner 함수 컨텍스트의 outerEnvironmentReference가 본인이 선언될 당시의 컨텍스트인 outer 함수 컨텍스트의 LexicalEnvironment를 참조하고 있는 것을 확인할 수 있습니다.
스코프 체인과정을 거치며 접근할 수 있는(유효한) 변수의 수가 늘어나는 것도 확인할 수 있습니다.
(크롬 개발자 도구 콘솔을 통해 스코프 체인을 확인할 수 있습니다.)

반응형

댓글