[Javascript] 렉시컬환경과 클로저(Closure) (Javascript 제대로 알고 쓰자) - 8

강준혁·2020년 12월 4일
3

JS를 공부하면서 가장 혼란스러웠던 내용 중 하나인 클로저와 렉시컬환경에 대해 알아보고자 한다.

렉시컬 환경

JS의 실행 중인 함수, 코드 블록 {...}, 스크립트 전체 는 렉시컬 환경(Lexical Environment) 이라 불리는 내부 숨김 연관 객체를 갖는다.

렉시컬 환경 객체는 다음의 두 부분으로 구성된다.

  • 환경 레코드 : 모든 지역변수를 프로퍼티로 저장하고 있는 객체. this 값과 같은 기타 정보도 여기에 저장됨.
  • 외부 렉시컬 환경에 대한 참조

코드를 보며 이해해보자.

let global = 'global' // #1
if (true) {
  let inner = 'inner' // #2
}

function foo() { // #3
  let bar = 'bar'
  console.log(bar + '/' + global);
}

foo(); // #4, bar/global 출력
  • #1 은 가장 외부에 있는 스크립트로, 전역 렉시컬 환경 하나를 갖는다.
  • #2 에서는 내부 렉시컬 환경이 생성되어, inner 라는 변수를 저장하고, global 이 존재하고 있는 전역 렉시컬 환경에 대한 참조를 갖는다.
  • #3 은 아직 실행되지 않은 함수이므로 렉시컬 환경을 갖지 않는다.
  • #4 는 함수가 실행되었으므로 내부 렉시컬 환경이 생성되어, bar 라는 변수를 저장하고, global 이 존재하고 있는 전역 렉시컬 환경에 대한 참조를 갖는다.

따라서 foo 함수가 호출되었을 때에는 다음과 같은 플로우로 진행된다.

  1. 내부에서 bar, global 변수에 대한 정보를 찾음.
  2. bar 변수를 내부 렉시컬 환경에서 획득.
  3. global 변수를 내부 렉시컬 환경에서 찾을 수 없음
  4. 외부 외부 렉시컬 환경에 대한 참조를 통해 전역 렉시컬 환경에 접근.
  5. global 변수를 획득하여 동작.

클로저(Closure)

클로저란 외부 변수를 기억하고 이 외부 변수에 접근할 수 있는 함수를 의미한다.
자바 스크립트의 함수는 생성될 당시의 환경을 기억하고 저장하며 이를 통해 외부 렉시컬 환경에 대한 참조가 가능하므로, 모든 함수가 클로저라고 할 수 있다.

클로저 사용 예시

간단하게는 다음과 같은 방식으로 쓰일 수 있다.

function logger(header) {
  return function(message) {
    console.log(`${header} : ${message}`);
  }
}

const orderLogger = logger('API'); // #1
const productLogger = logger('Product'); // #2

orderLogger('message'); // API : message
productLogger('message'); // Product : message
  • #2, #3 에서 함수가 실행될 때 각각의 내부 렉시컬 환경이 생성되고 header 변수에 대한 정보를 저장한다.
  • 함수가 실행이 되면 header 변수에 대한 정보를 내부 렉시컬 환경에서 찾아서 실행한다.
profile
백엔드 개발자

0개의 댓글