기본적으로 스코프를 알아야 클로저를 이해할수 있다고 생각한다.
식별자에 대한 유효범위
'식별자에 대한 유효범위'를 안에서부터 바깥으로 차례로 검색해 나가는 것
ex)
A함수 내부에 B함수
B함수 내부에 C함수
함수 C의 (LexicalEnvironment에 있는) outerEnvironmentReference는 함수 B의 LexicalEnvironment를 참조,
함수 B의 (LexicalEnvironment에 있는) outerEnvironmentReference는 함수 A의 LexicalEnvironment를 참조
이러한 과정을 통해 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능하다.
ex1)
var outer = function(){
var a= 1;
var inner = function(){
console.log(++a);
};
inner();
};
outer();
inner함수 내부에서 a를 선언하지 않았기 때문에 environmentRecord에서 값을 찾지 못하여 outerEnvironmentReference에서 상위 컨텍스트인 outer의 LexicalEnvironment에 접근하여 a를 찾아
++a
를 처리하고 값을 출력한다.
(outer 함수 종료 후 전부 가비지 컬렉터의 수집 대상이 된다.)
ex2) 외부 함수의 변수를 참조하는 내부 함수
var outer = function(){
var a= 1;
var inner = function(){
return ++a;
};
return inner();
};
var outer2 = outer();
console.log(outer2);
return inner()
로 인해 inner함수를 실행한 결과를 리턴하고 있다.
outer
함수의 실행 컨텍스트가 종료된 시점 :var outer2 = outer()
이후에는 가비지 컬렉터에 의해 전부 소멸
outer2는
typeof
로 number이다. 왜냐하면 return한inner()
는 결국 return 한++a
이기 때문이다.
어떤 함수에서 선언한 변수를 참조하는 내부함수에서만 발생하는 현상
outer 실행컨텍스트가 종료된 후에도
inner함수
를 호출할 수 있게 만들때
ex)
var outer = function(){
var a= 1;
var inner = function(){
return ++a;
};
return inner;
};
var outer2 = outer();
console.log(outer2()); //2
console.log(outer2()); //3
return inner
를 통해 inner함수의 실행 결과(값)이 아닌 inner 함수 자체를 반환했다.
outer함수의 실행 컨텍스트가 종료될 때 (var outer2 = outer();
) outer2 변수는 outer의 실행 결과인 inner함수를 참조하게 된다.
outer함수의 실행 컨텍스트가 종료되면
outer2
가 실행을 해도 inner함수가 실행이 되지만outer
의 실행 컨텍스트는 존재하지 않아야 한다.
하지만 가비지 컬렉터에 의해 어떤 값을 참조하는 변수가 하나라도 있다면 그 값은 수집 대상에 포함시키지 않습니다. ( 실행컨텍스트의 environmentRecord가 사라지지 않고 남아있다)
이로 인해
outer2
가 실행되어inner
함수는 실제 가비지 컬렉터에 의해 지워지지 않은outer
의 실행컨텍스트의 내용이 남아있어 이를 실행하는 것이 가능하다.
이와같은 현상을클로저
라고 한다.
- 어떤 함수에서 선언한 변수를 참조하는 내부함수에서만 발생하는 현상
(외부함수 outer에서 정의된 변수 a를 참조하는 내부함수 inner에서 발생하는 현상)- 외부 함수의 LexicalEnvironment가 가비지 컬렉팅 되지 않는 현상
(외부 함수 outer가 outer 실행컨텍스트가 종료된 후 해당 실행컨텍스트의 LexicalEnvironment가 가비지 컬렉팅에 의해 사라지지 않고 존재하여 필요시 사용할 수 있게 만든 것) => 어떤 값을 참조하는 변수가 하나라도 있기 때문
- 스코프 : 식별자에 대한 유효 범위
( 식별자 a를 사용하려는데 너를 몰라 그럼 너를 알려고 점점 외부함수로 가다가 var a가 선언된 곳을 찾으면 아 너는 그곳까지가 너의 범위다)- 스코프체인 : '식별자에 대한 유효범위'를 안에서부터 바깥으로 차례로 검색해 나가는 것
(위에서 설명한 선언된 곳까지 열심히 찾아가는 것 마치 체인같은 연결)- 클로저 : (내가 이해하기 쉽게 정리)
(1) 실제 변수에 대한 값을 가진 외부함수가 실행컨텍스트가 종료되고
(2) 내부함수를 사용하려는 새로운 식별자가 선언되고
(3) 새로운 식별자에 의해 (외부함수의 실행컨텍스트가) 가비지 컬렉터에 의해 사라지지 않고 실행컨텍스트가 존재하는 상태에서
(4) 새로운 식별자에 의해 내부함수를 실행할때
(5) 이미 존재한 실행컨텍스트에 의해 외부함수에서 존재하는 값을 사용할 수 있게 하는 역할
var outer = function(){
var a= 1;
var inner = function(){
return ++a;
};
return inner;
};
var outer2 = outer(); // (1),(2),(3)
console.log(outer2()); // (4),(5)
console.log(outer2());
코어자바스크립트