클로저는 JS 고유의 개념이 아니라 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서 사용되는 중요한 특성이다.
⇒ 따라서 ECMAScript 사양에 등장하지 않고 MDN에서는 클로저에 대해
“**클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다**”라고 정의
한다.
const x = 1;
function outerFunc() {
const x = 10;
// outerFunc 함수 내부의 중첩 함수 innerFunc가 정의되고 호출됨
// 이때 중첩 함수 innerFunc의 상위 스코프는 외부 함수
// outerFunc의 스코프이다.
**function innerFunc()** {
// 따라서 중첩 함수 innerFunc 내부에서 외부 함수 outerFunc의 x 변수에
// 접근할 수 있다.
**console.log(x); // 10**
}
innerFunc();
}
outerFunc();
⇒ 만약 innerFunc 함수가 outerFunc 함수의 내부에서 정의된 중첩 함수가 아니 라면 innerFunc 함수를 outerFunc 함수의 내부에서 호출해도 outerFunc 함수의 변수에 접근할 수 없다.
const x = 1;
function outerFunc() {
const x = 10;
innerFunc();
}
function innerFunc() {
**console.log(x); // 1**
}
outerFunc();
이와 같은 현상이 발생하는 이유는 JS가 렉시컬 스코프를 따르는 프로그래밍 언어이기 떄문이다.
JS 엔진은 함수를 어디서 호출했는지가 아니라 함수를 어디서 정의했는지에 따라 상위 스코프를 결정한다. 이를 렉시컬 스코프(정적 스코프)라 한다.
const x = 1;
// foo와 bar는 모두 전역에서 정의된 전역 함수다!
function foo() {
const x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // 1
bar(); // 1
foo 함수와 bar 함수의 상위 스코프는 전역이다.
스코프의 실체는 실행 컨텍스트의 렉시컬 환경이다.
“함수의 상위 스코프를 결정한다” = “렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장할 참조값을 결정한다”