Node, Javascript - Scope

1 minute read

본 포스트는 The modern Javascript Tutorial를 요약한 내용입니다.

코드 블록

코드 블록 {} 안에서 선언한 변수는 블록 안에서만 사용할 수 있습니다.

렉시컬 환경

실행 중인 함수, 코드 블록, 스크립트는 렉시컬 환경을 갖는다.
렉시컬 환경 객체는 두 부분으로 구성된다.

  1. 환경 레코드(Environment Record): 모든 지역 변수를 프로퍼티로 저장하고 있는 객체.
  2. 외부 렉시컬 환경에 대한 참조

변수

변수는 환경 레코드의 프로퍼티이다. 아래의 코드엔 렉시컬 환경이 하나만 존재한다.
scope1.png 스크립트 전체와 관련된 렉시컬 환경은 전역 렉시컬 환경이라고 한다. 전역 렉시컬 환경은 외부 참조를 하지 않아 null을 가리키는 걸 볼 수 있다. scope2.png 위의 스크립트는 아래와 같이 전역 렉시컬 환경이 변화한다.

  1. 스크립트가 시작되면서 스크립트 내 선언한 모든 변수가 렉시컬 환경에 올라간다. 이때, 변수의 상태는 특수 내부 상태인 uninitialized가 된다.
  2. let phrase를 만나며 undefined로 프로퍼티 값이 바뀌며 이 시점부터 사용 가능하다.
  3. phrase에 값이 할당 됨
  4. phrase의 값이 변경 됨

함수 선언문

함수 선언문으로 선언한 함수는 바로 초기화된다. 변수는 let을 만나 선언이 되기 전까지 uninitialized된 상태이지만 함수는 그렇지 않다. 하지만

let func = function() ... 

과 같이 정의된 함수는 해당되지 않는다.

내부, 외부 렉시컬 환경

함수를 호출해 시행하면 새로운 렉시컬 환경이 생성된다. 함수가 호출 중인 동안은 함수를 위한 내부 렉시컬 환경과 전역 렉시컬 환경 두 개를 갖게 된다. scope3.png 위의 스크립트는 아래와 같이 전역 렉시컬 환경이 변화한다.
내부 렉시컬 환경에는 함수의 인자인 name으로부터 유래한 프로퍼티 하나만 있고 외부 렉시컬 환경에는 phrase와 say를 프로퍼티로 갖고 있다. 내부 렉시컬 환경은 외부 렉시컬 환경에 대한 참조를 갖게 된다.
코드에서 변수에 접근할 땐, 내부 렉시컬 환경을 검색 범위로 잡는다. 해당 환경에서 찾지 못하면 내부 렉시컬 환경이 참조하는 외부 렉시컬 환경으로 확장하며 전역 렉시컬 환경일 때까지 반복한다. scope4.png 위와 같은 경우에 전역 렉시컬 환경에는 makeCounter 함수와 counter가 정의된다. 모든 함수는 함수가 생성된 곳의 렉시컬 환경을 기억한다. 함수는 Environment라는 숨김 프로퍼티를 갖는다. 여기에 함수가 만들어진 곳의 렉시컬 환경에 대한 참조가 저장된다.

가비지 컬렉션

함수 호출이 끝나면 렉시컬 환경이 메모리에서 제거된다. 그러나 위와 같은 경우는 Environment를 통해 도달할 수 있는 상태가 되어 삭제되지 않는다. 이러한 경우는 해당 함수를 호출하는 함수가 메모리에서 삭제되고 난 후에야 렉시컬 환경도 사라진다.

최적화 프로세스

이론상으로는 모든 변수 메모리에 유지되어야하나 자바스크립트 엔진이 주기적으로 최신화되며 사용하지 못하는 경우가 있다. scope5.png 이러한 경우, 함수 안에서 정의된 value가 프린트 되어야 할 것 같지만, 해당 변수는 정의되어 있지 않고 외부의 value만이 프린트 되는 것을 확인할 수 있다.

Leave a comment