Scope

JavaScript

Scope?

Scope(스코프)란 식별자에 대한 유효범위이다.

어떤 경계 A의 외부에서 선언한 변수는 A의 외부 뿐 아니라 A의 내부에서도 접근이 가능하지만, A의 내부에서 선언한 변수는 오직 A의 내부에서만 접근할 수 있다.

ES5까지의 자바스크립트는 전역공간을 제외하면 오직 함수에 의해서만 스코프가 생성되고, ES6에서는 블록에 의해서도 스코프 경계가 발생하면서 다른 언어와 스코프 개념이 비슷해졌다.

스코프(식별자의 유효범위)를 안에서부터 바깥으로 차례로 검색해나가는 것을 Scope Chain(스코프 체인) 이라고 부르는데, LexicalEnvironment의 두 번째 수집자료인 outerEnvironmentReference를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
var a = 1;
var outer = function(){
  var inner = function(){
    console.log(a); // undefined
    var a = 3;
  };
  inner();
  console.log(a); // 1
};
outer();
console.log(a); // 1

scope example

  • 시작 : 전역 컨텍스트 활성화
    • 전역 컨텍스트의 environmentRecord{a, outer} 식별자를 저장한다.
  • 1번째 줄과 2번째 줄 : 전역 스코프에 있는 변수 a에 1을, outer에 함수를 할당한다.
  • 10번째 줄 : outer 함수를 호출한다.
    • 전역 컨텍스트의 코드는 10번째 줄에서 임시중단되고, outer 실행 컨텍스트가 활성화되어 2번째 줄로 이동한다.
  • 2번째 줄 : outer 실행 컨텍스트의 environmentRecord{inner} 식별자를 저장한다. outerEnvironmentReference에는 outer 함수가 선언될 당시의 LexicalEnvironment가 담긴다.
  • 3번째 줄 : outer 스코프에 있는 변수 inner 에 함수를 할당한다.
  • 7번째 줄 : inner 함수를 호출한다.
    • outer 실행 컨텍스트의 코드는 7번째 줄에서 임시중단되고 inner 실행 컨텍스트가 활성화되어 3번째 줄로 이동한다.
  • 3번째 줄 : inner 실행 컨텍스트의 environmentRecord{a} 식별자를 저장한다. outerEnvironmentReference에는 inner 함수가 선언될 당시의 LexicalEnvironment가 담긴다. inner 함수는 outer 함수 내부에서 선언됐으므로 outer 함수의 LexicalEnvironment, 즉 [{outer, inner}]를 참조복사한다.
  • 4번째 줄 : 식별자 a에게 접근한다. 현재 활성화 상태인 inner 컨텍스트의 environmentRecord에서 a를 검색한다. a 가 발견되지만 아직 할당된 값이 없다.

    undefined 출력

  • 5번째 줄 : inner 스코프에 있는 변수 a 에 3을 할당한다.
  • 6번째 줄 : inner 함수 실행이 종료된다. inner 실행 컨텍스트가 콜 스택에서 제거되고, 바로 아래의 outer 실행 컨텍스트가 다시 활성화되면서, 앞서 중단됐던 7번째 줄의 다음으로 이동한다.
  • 8번째 줄 : 식별자 a에 접근하고자 한다. 자바스크립트 엔진은 활성화된 실행 컨텍스트의 LexicalEnvironment에 접근한다. 첫 요소의 environmentRecord 에서 a가 있는지 찾아보고, 없으면 outerEnvironmentReference에 있는 environmentRecord로 넘어가는 식으로 계속해서 검색한다. 두 번째, 즉 전역 LexicalEnvironmenta가 있으니 그 a에 저장된 값 1을 반환한다.

    1 출력

  • 9번째 줄 : outer 함수 실행이 종료된다. outer 실행 컨텍스트가 콜 스택에서 제거되고, 바로 아래의 전역 컨텍스트가 다시 활성화되면서, 앞서 중단됐던 10번째 줄의 다음으로 이동한다.
  • 10번째 줄 : 식별자 a에 접근하고자 한다. 현재 활성화 상태인 전역 컨텍스트의 environmentRecord에서 a를 검색한다. 바로 a를 찾을 수 있다.

    1 출력

  • 모든 코드의 실행이 완료된다. 전역 컨텍스트가 콜 스택에서 제거되고 종료된다.

출처
JavaScript: The Hard Parts (Will Sentance)
코어 자바스크립트 (정재남)