클로저는 외부 변수를 기억하고 이 외부 변수에 접근할 수 있는 함수를 의미한다.
클로저를 이해하기 위해선 실행컨텍스트의 개념부터 짚고 넘어가야한다.
함수의 실행컨텍스트
함수는 호출 될 때 함수의 실행컨텍스트 스택에 저장되었다가 실행이 끝나면 실행컨텍스트에서 제거된다. (힘수의 실행 컨텍스트가 생성될 때 함수의 lexical environment도 생성된다.) 이 실행컨텍스트의 lexical environment엔 함수의 지역변수의 정보와 이 함수의 상위 스코프의 대한 정보가 들어있다.
클로저를 위한 예시
const browsers = 'safari'
function outer() {
const browsers = 'chrome';
const inner = function() {
console.log(browers)
}
return inner
}
const defaultBrower = outer();
defaultBrower() // chrome을 출력
outer 함수는 중첩함수 inner를 defaultBrower에 반환하면서 생명주기를 마감한다.
outer 함수가 종료가 되면 그림에서 보는 것처럼 실행컨텍스트에서 제거된다.
outer 함수안의 chrome이 할당된 browsers변수 또한 생명주기를 마감하게되고, defaultBrower는 chrome에 접근할 수 없게 되는데 해당 코드를 실행하면 browers는 chrome이 나온다. 이는 inner가 클로저이기 때문인데, 중첩 함수 inner가 생명주기를 마감한 outer를 참조할 수 있다면 inner를 클로저라 한다.
설명이 복잡하지만
해당 코드를 실행하면, 전역 실행 컨텍스트가 스택에 쌓인 뒤 outer 함수가 쌓이게 된다.
이 때 outer 함수는 실행컨텍스트에서 실행되었다가 아래의 그림 처럼 제거되는데
- 전역 렉시컬 환경에 남아있는 defaultBrowser는 outer함수 내부에 있는 inner함수를 참조한다.
- 이 inner함수는 outer 함수 lexical environment에 있는 browser 변수를 참조하기 때문에 chrome이 할당된 browsers변수를 참조하게 되는 것이다.
- 이 때 inner함수를 실행 컨텍스트는 사라졌지만 내가 기억하고 있는 내부 슬롯에 저장된 상위 스코프에 의존하여 상위 스코프 내의 식별자를 참조할 수 있게 되는 것으로 이게 클로저의 개념이다.
즉, 상위 스코프의 식별자를 참조하고 있고 본인의 외부 함수보다 더 오래 살아 있다면 클로저인 것이다.
클로저 함수의 장단점
장점
- 데이터를 보존이 가능하다.
클로저 함수는 외부 함수가 실행컨텍스트에서 제거되더라도 외부 함수 내의 변수를 참조할 수 있다.
- 모듈화에 유리하다.
앞 선 예제 처럼 클로저 함수를 변수에 할당하면 독립적으로 변수의 값들을 유지할 수 있다.
단점
- 클로저함수는 실행될 때마다 각자의 참조 영역을 유지해야하기 때문에 메모리 사용량이 늘어나며, 이때 실행 환경에서 유지해야하는 데이터량이 많다면 많은 메모리를 사용하게 된다.
참조
https://hanamon.kr/javascript-클로저/
https://www.youtube.com/watch?v=PVYjfrgZhtU&ab_channel=우아한Tech