https://www.youtube.com/watch?v=PJjPVfQO61o&list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&index=84
💡 어떤 함수 내부에서 선언된 변수 a를 참조하는 내부 함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 끝난 후에도 변수 a가 사라지지 않는 현상
Recap
실행 컨텍스트 : 코드를 실행하는데 필요한 환경을 제공하는 객체
- 렉시컬 환경
- Record - 식별자와 식별자에 바인딩 된 값을 기록
- Outer - 외부 렉시컬 환경을 참조할 수 있도록 한다
클로저 예제
function outFn(x){
return function(){
return x + y;
}
}
const add = outFn(2)
console.log(add(7))
위의 코드가 실행되는 과정은 아래와 같다
- 전역 코드 평가가 이루어진다
- 위 코드에서 Global 렉시컬 환경의 Record에 들어갈 변수는 outFn, add 두가지
- 전역 평가가 이루어지는 중이어서 outer는 null
- 평가가 끝나면 순차적으로 코드 실행
- const로 선언된 add 변수에 값을 할당하기 위해 outFn함수가 실행
- 똑같이 outFn함수의 렉시컬 환경 생성, 평가 진행
- outFn함수 평가를 하면서 파라미터 x와 익명 함수를 호이스팅해서 record에 기록
- outer는 상위 스코프인 global 렉시컬 환경을 가리킨다
- record에 선언된 파라미터 x에는 const add = outFn(2) 라고 되어있으니 2라는 값을 할당
**outFn함수의 outer가 global렉시컬 환경을 가리키는 이유
- global 렉시컬 환경이 만들어지면서 outFn함수의 변수가 입력되었기 때문.
- 즉, 어떤 환경에서 변수가 선언되었는지가 중요하다!**
- 이후 outFn함수에 실행할 코드가 없으니 callstack에서 outFn 렉시컬 환경은 pop되고
다시 global 렉시컬 환경으로 들어와서 outFn함수의 return값인 익명 함수를 add변수에 할당하고 record에 있는 add 변수에 익명 함수를 할당한다.(const add = function())
- 마지막 코드인 console.log 함수를 실행
- 위에서 add 변수는 익명 함수이므로 다시 add의 렉시컬 환경 생성
const add = function(y){ return x+ y }
- 변수 y를 호이스팅해서 record에 기록하고 outer는 상위 렉시컬 환경인 sum을 가리킨다
근데 아까 실행이 끝나고 pop 해버렸기 때문에 지금 콜스택에는 outFn 렉시컬 환경이 없다.
그런데도 outer가 outFn 렉시컬 환경을 가리킬 수 있는 이유는
위에서 설명했듯 익명 함수가 선언되는 시점이 outFn 함수 내부 평가 과정에서 익명 함수가 선언되기 때문에 outer가 outFn을 가리킬 수 있는 것
c. 렉시컬 환경을 생성했으니 callstack에 push
d. console.log(add(7))이니 y변수에 7을 기록
- 다음 코드인 return x + y를 실행
- outer를 통해 x변수에 할당된 값을 찾아 x + y 실행
- return 값 9가 나온다
콜스택에 렉시컬환경이 존재하지 않아도 outer를 통해 참조할 수 있는 현상을 클로저라 한다