클로저란 ? (클로저의 핵심 3가지)
1) 함수를 선언할 때 만들어지는 유효범위가 사라진 후에도 호출할 수 있는 함수
2) 이미 생명주기상 끝난 외부 함수의 변수를 참조하는 함수
3) 자신이 생성될 때의 스코프에서 알 수 있었던 변수들 중 언젠가 자신이 실행될 때 사용할 변수들만을 기억하여 유지시키는 함수
예시 1) 외부함수의 변수를 참조하는 내부함수
var outer =function(){
var a =1;
var inner=function(){
console.log(++a);
};
inner();
};
outer(); //실행결과를 맞춰보세요!
+ 실행결과: 2
inner함수 내부에서는 a를 선언하지 않았기때문에 environmentRecord에서 값을 찾지 못하므로 outer의 LexicalEnvironment에 접근해서 a를 찾는다. outer 함수의 실행컨텍스트가 종료되면 LexicalEnvironment에 저장된 식별자에 대한 참조(a,inner)를 지운다. 그러면 각 주소에 저장되어 있던 값들은 자신을 참조하는 변수가 없어져서 가비지 컬랙터의 수집대상이 된다.
+실행컨텍스트가 수집하는 정보 2가지 : VariableEnvironment & LexicalEnvironment
- VariableEnvironment : 현재 컨텍스트 내의 식별자들에 대한 정보 담긴 객체(변경 사항은 반영되지 x)
- environmentRecord : 매개변수명, 변수의 식별자, 선언한 함수의 함수명 등을 수집
- outerEnvironmentReference : 바로 직전 컨텍스트의 LexicalEnvironment 정보 참조
- LexicalEnvironment : 변경 사항이 실시간으로 반영되는 정보 담긴 객체
- environmentRecord
- outerEnvironmentReference
예시2) 외부함수의 변수를 참조하는 내부함수 (return)
var outer =function(){
var a =1;
var inner=function(){
return ++a;
};
return inner();
};
var outer2=outer();
console.log(outer2); //실행결과를 맞춰보세요!
+ 실행결과: 2
위의 예제와 마찬가지로 outer 함수의 실행 컨텍스트가 끝나면 a변수를 참조하는 대상이 없어진다. 따라서 a,inner는 가비지 컬레터의 수집대상이 되어 소멸된다.
예시1과 예시2는 outer함수의 실행 컨텍스트가 종료되기 이전에 inner함수의 실행 컨텍스트가 미리 종료되어있기 때문에 이후 별도로 inner함수를 호출할 수 없다.
++그렇다면 outer의 실행컨텍스트가 종료된 후에 inner함수를 호출할 수 있게 하고싶다면?++
var outer =function(){
var a =1;
var inner=function(){
return ++a;
};
return inner; //실행결과가 아닌 함수자체를 반환
};
var outer2=outer();
console.log(outer2()); //실행결과를 맞춰보세요!
console.log(outer2()); //실행결과를 맞춰보세요!
+ 실행결과: 2 3
inner함수는 outer함수 내부에서 선언됐으므로, outer함수의 LexicalEnvironment가 담긴다. outer에서 선언한 변수 a에 접근해서 1만큼 증가시키고 2를 반환하고, inner함수의 실행 컨텍스트가 종료된다. 다시 outer2를 실행하면 a는 3을 반환한다.
가비지 컬렉터는 어떤 값을 참조하는 변수가 하나라도 있다면 그 값은 수집 대상에 포함시키지 않는다. 따라서 outer함수는 실행종료시점에 inner함수를 반환하기 때문에 외부함수인 outer의 실행이 종료되더라도 outer2를 실행함으로써 호출될 가능성이 열린것이다. 따라서 수집대상에서 제외되고 inner함수가 이 변수에 접근할 수 있는 것이다.
✨클로저는 어떤 함수에서 선언한 변수를 참조하는 내부함수에서만 발생하는 현상이다. 위의 예제와 같이 가비지 컬렉터의 수집대상에서 제외되는 경우는 지역변수를 참조하는 내부함수가 외부로 전달된 경우이다. 따라서 클로저는 외부함수의 LexicalEnvironment가 가비지 컬렉팅 되지 않는 현상을 말한다. 다시 한번 말하자면, 클로저란 어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수a가 사라지지 않는 현상을 말한다.
'JS' 카테고리의 다른 글
[JS] 콜백함수, 콜백지옥 (0) | 2022.05.13 |
---|---|
[JS] This, Binding (0) | 2022.05.12 |
[JS] 실행컨텍스트, 호이스팅, 스코프체인 (0) | 2022.05.11 |
[JS] 자바스크립트 데이터 타입 (0) | 2022.05.11 |