이번에 정리할 내용은 Closure와 Lexical Scope에 관한 내용입니다.
최근 면접을 보고 있는데 자바스크립트 코어에 관한 부분에서 부실한 점이 많아 차근차근 정리합니다.
🤔 Closure? Lexical Scope?
Closure가 뭘까요? 한 걸음 Closer~ 내 맘~ 아니구요.
클로저는 독립적인 변수를 가르키는 함수입니다.
아래 코드가 있습니다.
function outerFunc() {
var x = 10;
var innerFunc = function () {
var y = 20;
console.log(x);
};
innerFunc();
}
outerFunc();
outerFunc이 선언되어 있고 함수 내부에는 innerFunc이 선언되고 실행되고 있습니다. 여기서 선언했다는 표현에 포인트를 맞춰야합니다. 자바스크립트에는 Scope라는 것이 있습니다. 함수의 유효범위, 즉 해당 함수가 사용할 수 있는 변수에 접근할 수 있는 범위를 나타냅니다. outerFunc은 전역에서 선언 되어 전역 범위(Global Scope)를 가집니다. innerFunc는 outerFunc 안에서 선언 되어 지역 범위(Local Scope)를 가집니다.
전역범위는 어디서든 접근할 수 있으며, 지역범위는 지역 내에서만 접근할 수 있습니다.
해당 함수를 실행하게 되면, x 값이 찍혀나옵니다. 어떻게 innerFunc 내부에 없지만 " 10 "이라는 값이 출력될까요?
Scope는 함수가 호출 되는 곳이 아닌 함수가 선언 되는 곳에 따라 결정이 됩니다. 이를 Lexical Scoping 이라고 합니다.
InnerFunc Scope에 없다면 Scope Chain을 따라 상위 Scope에서 변수 x를 찾습니다. Scope Chain이 어떻게 연결 되는지는 실행컨텍스트(Execution Context)에 대해 찾아보시면 좋을거 같습니다. innerFunc의 상위 Scope는 outerFunc가 되며 그 상위는 Global Scope가 됩니다.
아래 코드를 봅시다.
function outerFunc() {
var x = 10;
var innerFunc = function () { console.log(x); };
return innerFunc;
}
/**
* 함수 outerFunc를 호출하면 내부 함수 innerFunc가 반환된다.
* 그리고 함수 outerFunc의 실행 컨텍스트는 소멸한다.
*/
var inner = outerFunc();
inner(); // 10
이번에는 outerFunc의 return 값으로 innerFunc을 줬습니다. 그리고 inner에 outerFunc()를 실행해 innerFunc이 반환되어 담기게 되고, 이를 실행하면 10이라는 값이 나옵니다. 여기서 의문이 생깁니다. innerFunc 내부에는 console.log(x) 밖에 없고 x는 outerFunc 내부에 있는데 outerFunc 실행 컨텍스는 이미 innerFunc을 반환해주고 스택에서 제거 되었는데 어떻게 x값을 받아오는거지? 이렇게 자신을 포함하고 있는 외부 함수보다 내부함수가 더 오래 유지되는 경우, 외부함수 밖에서 내부함수가 호출 되어 외부함수의 지역변수에 접근할 수 있는 함수를 클로저(Closure)라고 한다.
Closuer(클로저)
클로저는 반환된 내부함수가 자신이 선언되었을때 환경(Lexical Environment)인 Scope를 기억하여 자신이 선언 되었을때 그 Scope에 접근할 수 있는 함수를 의미한다. 클로저에 의해 참조(접근)되는 외부변수를 자유변수(Free Variable)라고 부릅니다. 다시 말해 외부함수가 반환되었더라도 외부변수를 필요로 하는 내부함수가 하나라도 있다면 외부변수는 유효한 변수가 되며 실제 변수에 접근합니다.
이전 코드에서 보았듯이, inner()는 innerFunc을 담고 있고 outerFunc에 있는 x에 접근하여 console.log(x)를 출력하게 됩니다.
'Programming > JavaScript' 카테고리의 다른 글
[JS] Async & Await .00 (0) | 2021.01.01 |
---|
삽질의 기록과 일상을 남기는 블로그입니다. 주로 React Native를 다룹니다.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!