📝 Summary
- 클로저는 함수와 그 함수 주변의 상태의 주소 조합이다.
- 클로저의 함수는 어디에서 호출되느냐와 무관하게 선언된 함수 주변 환경에 따라 접근할 수 있는 변수가 정해진다.
JavaScript에서는 다른 컴퓨터 언어와는 조금 다른 특성을 종종 가지고 있는데, 그 중 클로저라는 개념에 대해서 알아보자. MDN의 클로저 정의는 다음과 같다.
"함수와 함수가 선언된 어휘적(lexical) 환경의 조합을 말한다. 이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다."
특이하게도 자바스크립트는 함수가 호출되는 환경과 별개로 기존에 선언되어 있던 환경, 즉 어휘적 환경을 기준으로 변수를 조회하려고 한다. 이와 같은 이유로 "외부 함수의 변수에 접근할 수 있는 내부 함수"를 클로저 함수라고 한다.
1️⃣ 클로저란?
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). - mdn (2023)
클로저는 함수와 그 함수 주변의 상태의 주소 조합이다.
다시 말해, 클로저는 함수와 그 함수가 접근할 수 있는 변수의 조합이다.
2️⃣ 클로저를 어떻게 구분할 수 있을까?
그렇다면 아래 코드에서는 무엇이 클로저일까?
const globalVar = '전역 변수';
function outerFn() {
const outerFnVar = 'outer 함수 내의 변수';
const innerFn = function() {
return 'innerFn은 ' + outerFnVar + '와 ' + globalVar + '에 접근할 수 있습니다.';
}
return innerFn;
}
위 코드에 있는 함수부터 찬찬히 살펴보면
- 함수 outerFn에서는 변수 globalVar에 접근할 수 있다.
- 함수 innerFn에서는 변수 globalVar와 함수 outerFn 내부의 outerFnVar에 접근할 수 있다.
즉, 위 코드에서 클로저는 두 조합을 찾을 수 있다.
- 함수 outerFn과 outerFn에서 접근할 수 있는 globalVar
- 함수 innerFn과 innerFn에서 접근할 수 있는 globalVar, outerFnVar
3️⃣ 클로저는 왜 중요할까?
변수의 접근 범위인 스코프와 비슷한 개념인데, 왜 따로 클로저만 구분을 할까? 클로저의 함수는 어디에서 호출되느냐와 무관하게 선언된 함수 주변 환경에 따라 접근할 수 있는 변수가 정해지기 때문이다.
innerFnOnGlobal은 outerFn 내부의 innerFn의 주솟값을 가진다. 그다음 줄에서 innerFnOnGlobal을 호출()한다. 이때, innerFnOnGlobal은 innerFn 밖에 있기 때문에 outerFnVar에는 접근하지 못한다고 생각할 수 있는데, 실제로는 접근할 수 있다.
왜 접근할 수 있을까? innerFn 함수가 최초 선언되었던 환경에서는 outerFnVar에 접근할 수 있기 때문이다. innerFnOnGlobal은 innerFn의 주솟값을 가지고 있고, innerFn은 클로저로서 outerFnVar에 접근할 수 있기 때문이다. 이 “환경”을 어휘적 환경(Lexical Environment)라고 한다.
코드를 직접 실행해보면 'innerFn은 outer 함수 내의 변수와 전역 변수에 접근할 수 있습니다.' 라는 문자열이 리턴되어 message 변수에 담겨 로그로 출력된다. 만약 클로저가 JavaScript에 없는 개념이라면, outerFnVar에 접근할 수 없어 에러가 났을 것이다.
디버거에서도 아래와 같이 클로저이기 때문에 접근할 수 있었던 outerFnVar는 따로 분류하고 있는 모습을 확인할 수 있다.
실제 클로저를 사용할 때는 outerFn, innerFn처럼 함수가 함수를 리턴하는 패턴을 자주 사용하고, outerFn을 외부 함수, innerFn을 내부 함수라고 통칭한다.
// 클로저 사용 패턴 1
function outerFn() {
const outerFnVar = 'outer 함수 내의 변수';
const innerFn = function() {
return 'innerFn은 ' + outerFnVar + '에 접근할 수 있습니다.';
}
return innerFn;
}
문제풀이
다양한 실험들
** return / return
-> 잘 작동한다
** const 변수 / return 함수
-> 변수만 정의하는 것이기 때문에 결과값 변화가 없어 보인다
** const 변수 / return 변수
-> 퀴즈에 나오는 예시처럼 memolog는 innerFn의 스코프에 있기 때문에 접근이 불가하다.
'FE > JavaScript' 카테고리의 다른 글
[JS] Scope 문제 풀이 - 다양한 패턴 (0) | 2023.03.03 |
---|---|
[JS] 클로저 활용 (함수, 커링, 모듈) (0) | 2023.03.03 |
[JS] 변수 선언 시 주의할 점 (let, const 쓰기) ... Var bye!!!! (0) | 2023.03.03 |
[JS] 스코프(Scope) (0) | 2023.03.02 |
[JS] 얕은 복사와 깊은 복사 (0) | 2023.03.02 |