스코프
식별자가 유효한 범위
전역 스코프
어디서든 참조 가능
지역 스코프
자신의 지역 스코프, 하위 스코프에서만 참조 가능
클로저
생명주기가 종료된 외부함수의 식별자를 참조하는 것
상위 스코프의 식별자를 참조하고 있고 본인의 외부 함수보다 더 오래 살아있는 것
가비지 컬렉터는 참조 카운트가 0인 것만 수집한다. 참조 카운트가 1 이상인 것들은 수집하지 않는다.
어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상
let x = 1
function wrapper(){
const x = 10;
const inner = function(){
console.log(x)
}
return inner
}
const ella = wrapper();
console.log(ella)
- 글로벌 렉시컬 환경이 생성되고
-> 변수 x와 wrapper함수, ella변수를 호이스팅해서 글로벌 렉시컬 스택의 Record에 기록하고 콜스택에 push
-> 이 과정이 코드 평가 과정
- 코드 평가 과정이 끝나고 순차적으로 코드 실행.
-> ella변수에 값을 할당하기 위해 wrapper함수 실행
- wrapper함수의 렉시컬 환경 생성, wrapper함수 내부 코드 평가가 이루어진다
-> 변수 x, inner가 호이스팅해 Record에 기록
-> Outer Environment에는 상위스코프인 Global 렉시컬 환경을 가리킨다.
-> 그리고 콜스택에 wrapper렉시컬 환경을 push
- wrapper함수 내부 코드 평가가 끝나고 순차적으로 실행
-> 변수x에 10을 할당, inner에 익명함수 할당하는 등 모든 변수에 값들을 재할당
-> 모든 코드의 실행이 끝나면 wrapper렉시컬 환경은 콜스택에서 pop되어 사라진다
- 다시 글로벌 변수인 ella로 돌아와 ella변수의 값으로 otuer함수의 리턴값인 inner함수를 할당
5.다음 console.log()에서 ella를 실행시키니 콜스택에 ella의 렉시컬 환경을 생성해 Outer Environment에서 wrapper함수를 가리킨다
- wrapper함수는 이미 (3)에서 pop되어 사라졌는데 어떻게 ella의 렉시컬 환경의 Outer Environment는 wrapper를 가리킬 수 있을까?
-> 자바스크립트는 선언 시점에 상위 스코프가 결정되는 렉시컬 스코프(정적 스코프)를 따르기 때문
-> wrapper함수의 평가 과정에서 inner함수의 Outer Environment에 먼저 등록해 놓기 때문에 이미 사라진 wrapper함수를 가리킬 수 있는 것
- 다시 inner함수를 실행시키는 과정으로 돌아가서 console.log(x)를 만나게 되는데 x는 inner함수 내부에 존재하지 않는다.
- 그럼 Outer Environment를 타고 wrapper함수로 가서 x를 찾는다.
- wrapper에 x = 10이 있으니 10이라는 값을 반환.
- 만약 x의 값을 찾지 못하면 Reference Error!
- 그리고 모든 실행을 마친 ella 렉시컬 환경이 콜스택에서 pop
- 마지막으로 글로벌 렉시컬 환경도 pop되고 앱 종료
wrapper의 Lexical Environment는 콜스택에 존재하지 않지만 ella의 Outer Environment가 가리키고 있는 wrapper의 지역변수 x가 사라지지 않는 현상을 ‘클로저’라고 한다.
그리고 클로저에 의해 참조되는 변수 x를 자유변수 라고도 한다
https://www.youtube.com/watch?v=MbYShFxp-j0
https://youtu.be/PVYjfrgZhtU?si=LhYQ9_OKX9HifU0k
https://youtu.be/xJtVVLPxgco?si=4pD5oKk7-7JjSgRK
https://youtu.be/LL0DGc5pg7A?si=7DEeaC9QcTnC8uCJ
https://youtu.be/EWfujNzSUmw?si=jIm8H1F24UClhqox
https://youtu.be/PJjPVfQO61o?si=8HQHC_82HVLivK-K
https://youtu.be/tpl2oXQkGZs?si=9MWmltyPgPYgYc35