외부함수의 변수에 내부 함수에서 접근할 수 있는 것을 의미합니다. 실행 컨텍스트의 스코프 정보에 따라 사용할 수 있는 것이며 다른 언어와 비슷한 듯 하지만 조금 다르게 실행됩니다. 스코프를 이해하는 것이 중요하며 자바스크립트 코드를 이해하는데 큰 도움이 됩니다.
간단한 예제를 통해 클로저에 대해 살펴보겠습니다.
let a = () => {
let text = 'hello';
let b = ()=>{console.log(text);}
b();
}
a(); // hello
a함수는 text라는 변수를 가지고 있고 내부함수인 b 함수에서 text를 사용할 수 있습니다.
만약 외부함수인 a함수 실행되고 소멸했을 때도 b함수에서 text를 사용할 수 있는지 확인해보겠습니다.
let a = () => {
let text = 'hello';
let b = ()=>{console.log(text);}
b();
return b;
}
let closure = a(); // hello
closure(); // hello
a함수가 실행되고 나서 b함수를 리턴합니다.
리턴된 b함수는 sub에 저장합니다. closure함수를 실행할 경우 a에 저장했었던 text를 정상적으로 불러오는 것을 알 수 있습니다. 이미 외부 함수가 소멸하더라도 접근할 수 있으며 b의 컨텍스트에 저장되어 있는 것을 확인할 수 있습니다.
만약 b 선언과 실행 이후 text를 교체하면 어떻게 될까요?
let a = () => {
let text = 'hello';
let b = ()=>{console.log(text);}
b();
text = 'why?'
return b;
}
let closure = a(); // hello
closure(); // why?
hello
와 why?
가 순차적으로 찍힙니다.
a함수기 종료되는 지점의 text 변수(why?)를 b의 컨텍스트에 저장하고 있는 것을 확인 할 수 있습니다.
디버깅을 통해 closure함수의 스코프체인을 확인하면 text: 'why?'가 저장되어 있는 것을 볼 수 있습니다.
만약 a의 내부가 아닌 외부에서 값을 바꾸고 싶을 땐 어떻게 하면 될까요?
let a = () => {
let text = 'hello';
return {
get_text: ()=>{console.log(text);},
set_text: (t) => { text = t }
};
}
let closure = a();
closure.get_text();
closure.set_text('hi');
closure.get_text();
이번에는 return 값으로 get_text
함수와 set_text
함수를 object에 담아 리턴하도록 하였습니다. get함수를 통해 text의 값을 얻을 수 있고 set으로 값을 입력받아 text를 수정할 수 있습니다. 이런식으로 외부에서 내부 값을 간접적으로 변경할 수 있습니다.