Posts You don't know JS Yet 2부 - 2장 렉시컬 스코프
Post
Cancel

You don't know JS Yet 2부 - 2장 렉시컬 스코프

컴파일 중 JS 엔진은 스코프의 지도를 완성한다. 이를 렉시컬 스코프라고하며 이때 렉시컬은 컴파일의 첫번째 단계인 렉싱을 의미한다.

이번 장에서는 스코프를 더 잘 이해하고, 이를 위해 JS 엔진이 프로그램을 처리하는 방법을 살펴보자

2.1 구슬과 양동이

변수가 어느 스코프에 들어가는지를 구슬이 어느 양동이에 들어가는지로 비유해서 설명함

  • 스코프는 부모 스코프에 온전히 포함되기에 한 스코프가 두 개의 바깥 스코프에 동시에 포함되는 일은 일어나지 않는다
  • 각 변수는 어디에서 정의되었느냐에 따라 들어갈 곳이 결정되며, 어디서 접근가능한지에 따라 결정되지 않는다.
  • 선언이 이뤄진 스코프와 동일한 스코프에 있는 변수 참조, 혹은 더 깊은 스코프에 있는 변수 참조는 해당 스코프와 동일한 색이 된다.
  • 스코프에 있는 표현식은 자신과 그 위에 속한 스코프에만 접근이 가능하고, 안쪽 스코프는 접근이 안된다. 먼저 자신의 스코프를 먼저 찾고, 없으면 상위 스코프에서 찾는다.
  • 이러한 분류는 컴파일 중 일어나며, 탐색또한 이미 컴파일 단계에서 마친 상태이기에 런타임에서 불필요한 탐색이 일어나지 않는다

2.2 JS 엔진 구성원 간의 대화

컴파일러가 var students = [ ... ] 을 만났을때는

  1. 스코프 매니저에 students 라는 변수가 있는지 물어봄. 있다고 하면 컴파일러는 선언을 무시함. 없다고 하면 프로그램이 실행될 때 스코프 매니저에게 해당 스코프에 students라는 이름의 변수를 생성해달라고 요청함
  2. 컴파일러는 프로그램 실행 시점에 엔진이 실행할 students = [] 할당문에 대한 코드를 생성함. 엔진은 실행시 이 코드를 보고 스코프 매니저에게 students 라는 변수가 있는지 물어봄. 없다고 하면 스코프를 타고 올라가며 찾는다. 이후 변수를 undefined로 초기화해 준비하고, 여기에 배열([...])의 참조를 할당한다.

추가적으로 컴파일러는 함수나 블록 스코프를 만나면 스코프 매니저에게 새로운 스코프를 준비하라고 알린다.

2.3 중첩 스코프

모든 스코프는 한번이든 여러번이든 실행될 때마다 스코프에 해당하는 스코프 매니저 인스턴스를 갖게 된다. 그리고 스코프가 실행될 때마다 자동으로 해당 스코프 내 모든 식별자가 스코프에 등록된다 ( = 호이스팅)

  • 스코프 시작부분에 식별자가 function 선언과 함께 등장했으면 해당 변수는 연관된 함수 참조로 자동 초기화된다
  • 식별자가 var로 선언되었다면 해당 변수는 자동으로 undefined로 초기화되어 바로 사용가능한 상태가 된다.
  • var로 선언되지 않았으면 초기화되지 않은 상태(TDZ)가 되어 엔진에 의해 선언 및 초기화가 완전히 끝날때까지 사용할 수 없다

만약 상위 스코프를 계속 탐색했지만 원하는 식별자를 찾지 못하면 오류 발생 상태가 조성된다. 이때는 프로그램이 엄격모드인지 아닌지와 변수의 역할에 따라 오류를 다르게 처리한다

undefined에 관한 혼란

  • 변수가 소스 역할을 할때 식별자를 찾지 못하면 해당 변수는 선언되지 않은 변수로 간주되어 ReferenceError를 발생 시킨다.
  • 변수가 타깃 역할을 하고 프로그램이 엄격모드일때 해당 변수는 선언되지 않은 변수로 간주되어 ReferenceError가 발생한다.

이때 발생하는 에러는 ReferenceError: xxx is not defined 인데, JS에서 not definedundefined는 전혀 다르다.

undefined는 선언은 되어있는데 (변수는 발견하였는데) 해당 시점에 값이 없는 경우를 뜻하고, ReferenceError는 선언자체가 일어나지 않은 경우다

하지만 typeof 연산자를 사용하면 둘다 똑같이 undefined를 반환하기에 이는 혼란스럽다

1
2
3
var studentName;
typeof studentName;  // "undefined"
typeof notExist;     // "undefined"

전역변수의 갑작스러운 등장

선언되지 않은 변수가 타깃역할을 하고 엄격모드가 아닐때, 타깃 할당이라는 목적을 달성하기 위해 전역 스코프의 스코프 매니저가 돌발적으로 전역 변수를 만들어 버린다.

이러한 동작은 버그가 발생할 확률이 높기에 엄격모드가 필요한 좋은 예시이다.

This post is licensed under CC BY 4.0 by the author.

You don't know JS Yet 2부 - 1장 스코프

You don't know JS Yet 2부 - 3장 스코프 체인

Comments powered by Disqus.