클로저는 두개의 함수로 만들어진 환경으로 이루어진 특별한 객체의 한 종류이다. 여기서 환경이라 함은 클로저가 생성될 때 그 범위에 있던 여러 지역 변수들이 포함 된 context
를 말한다. 이러한 범위는 자바스크립트 코드를 실행하기 위해 발생하는 컴파일 단계에서 결정된다.
클로저를 통해서 자바스크립트에는 없는 비공개 속성/메소드, 공개 속성/메소드 처럼 구현 할 수 있다.
Lexical Scope
자바스크립트 코드를 실행할 때 컴파일 단계에서 몇가지 일이 일어난다. 그중 하나인 토크나이징과 렉싱이 있다.
토크나이징
문자열을 나누어 토큰으로 만드는 과정
|
|
위와 같은 구문을 만나게 되면, 아래와 같은 토큰으로 나눈다.
|
|
렉스타임
토크나이징의 결과물인 토큰을 분석하여 생성된 토큰에 의미를 부여하는 것을 렉싱이라고 하며, 이 과정을 렉스타임이라고 한다.
렉시컬 스코프
개발자가 코드를 작성할때 변수를 어디에 작성하는가를 바탕으로 렉스타임에 토큰이 분석되며 스코프가 결정된다. 이때 구성된 유효 범위를 렉스컬 스코프라고 한다.
|
|
위의 코드가 실행될때 스코프 버블은 bar 안쪽에서 부터 시작되어 올라간다.
코드를 해석하는 과정에서 상위에서 하위로 쌓이는 구조로 해석되기 때문에, scope에 대한 검색은 기본적으로 하위에서 상위는 되지만 상위에서 하위로의 검색은 불가능하다.
|
|
정리
컴파일레이션의 렉싱 단계에서 모든 변수들이 어디서 어떻게 선언되었는지 바탕으로 실행 단계에서 스코프를 구성하고, 이렇게 구성되는 스코프가 렉시컬스코프이다.
클로저 생성하기
- 내부 함수가 익명 함수로 되어 외부 함수의 반환값으로 사용된다.
- 내부 함수는 외부 함수의 실행 환경에서 실행된다.
- 내부 함수에서 사용되는 변수는 외부 함수의 변수 스코프에 있다.
|
|
outer
함수를 실행시키는 context
에는 name
이라는 변수가 존재하지 않지만, inner
함수가 outer
함수 내부에 선언된 name
을 참조하기 때문에, name
변수에 대한 정보를 알 수 없는 outer
변수 외부환경에서도 정상 출력된다.
|
|
위 코드에서 callFunc
를 클로저라고 한다. callFunc
호출에 의해 name
이라는 값이 console에 출력되는데, “Warning“이 아니라 “closure“이다. 즉, outer
함수의 context 에 속해있는 변수를 참조하는 것이다. 여기서 outer
함수의 지역변수로 존재하는 name
변수를 free variable(자유변수) 라고 한다.
이처럼 외부 함수 호출이 종료 되더라도 외부 함수의 지역 변수 및 변수 스코프 객체의 체인 관계를 유지할 수 있는 구조를 클로저라고 한다.