Closure
클로져란 어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달시 A의 실행컨텍스트가 종료된 이후에도 변수 a가 사라지지않고, 기억하고 접근할 수 있는 것을 의미한다.
(코어JS, JS info 출처) 다양하게 설명했지만, 제일 이해가 잘 됐다.
Lexical Environment
함께 이해해야될 부분
렉시컬환경은 두부분으로 구성
Lexical Environment는 함수 호출시 새롭게 자동으로 만들어진다.
그 내부엔 함수 호출시 넘겨받은 매개변수, 함수의 지역변수가 저장됨.
그래서 이 [[Environment]]프로퍼티로 함수가 처음 생성된 곳을 알 수 있게 하고 스코프 체인과 같이 Lexical Environment에서 변수를 찾고 없으면 상위, 즉 outer Lexical Environment 이동해 변수를 참조합니다.
이떄 변숫값 갱신은 변수가 저장된 Lexical Environment에서 됩니다.
function outer() {
let count = 0;
let inner = function () {
console.log(count++);
}
return inner;
}
let countMachine = outer();
countMachine();
countMachine();
countMachine();
여기 console에 적힌 값은 0, 1, 2 로 나올 것이다.
이때 countMachine가 실행될때마다 새로운 lexical Environment가 생긴다.
이 lexical Environment는 countMachine.[[Environment]]를 외부 렉시컬 환경으로 참조하게 되고,
count라는 변수가 countMachine에는 없기때문에 외부 렉시컬환경을 참조해서 outer에 있는 count를 사용합니다.
이 변수 count++함으로 (갱신된 변숫값은 저장된 곳에서 변함) 계속 count값이 저장되고 업데이트된다.
- 유의점
메모리 누수
GC(Garbage Collector)가 코드가 실행되고(함수호출이 끝나고) 함수에 대응하는 렉시컬환경이 메모리에서 제거된다. 이때 변수들도 모두 사라짐.
하지만 클로저를 이용하게 되면 외부함수 사용이 끝나더라도 내부함수에서 외부함수의 변수를 사용하고 있기 때문에 GC가 제거하지 못해서 메모리사용이 계속 된다.
(렉시컬 환경이 유지됨)이로 인해 생기는 메모리 누수를 없애기 위해서는 사용이 끝난 클로저 함수를 (위의 코드를 예시로) countMAchine = null;
삭제해주면 메모리에서 삭제된다.