우리가 실행컨텍스트를 배웠다면 클로저는 이해하기 쉽다.
function f1() {
let i = 0;
return function () {
i += 1;
console.log(i);
}
}
const ff = f1();
ff(); //1
ff(); //2
ff(); //3
이처럼 함수에 리턴되는 함수를 만들고 리턴된 함수를 다른 변수에 담아 사용한다면 참조되는 Environment Record가 삭제되지 않고 남아있다는 건데 이렇게 말하면 이해하기 힘들 것 같긴 하다.
하지만 실행컨텍스트를 생각한다면 금방 이해된는데 차근차근 봐보자
f1
함수가 전역 함수로 선언되어 있기 때문에 <f.o>에 올라가게 된다.ff
변수가 const
선언문으로인해 Declarative Environment Record에 UIY
으로 올라간다f1
함수는 function 선언문이니 실행할 것은 아니니 넘어간다const ff = f1()
문을 할당해줘야 하기 때문에 f1
함수를 ()
실행한다.f1
함수 실행f1
함수가 실행되었으니 이제 ECS에 f1
함수 컨텍스트 스택이 올라가게 되고 f1
의 레코드 가 만들어진다.f1
함수 평가let i
가 있으니 i
를 f1
함수 실행 환경 레코드에 올리고 return은 실행시 반환될 것이니 아직 대기한다f1
함수 실행let i=0
을 통해 i
에 0을 할당하고 return문을 실행한다f1
함수 종료 -> 전역 실행으로 돌아감f1
함수가 종료되면서 실행 컨텍스트는 pop되고 f1
함수가 return한 익명함수는 const ff = f1();
를 통해 ff
라는 변수에 할당된다f1
의 함수가 실행 컨텍스트 스택에서 pop 될 때 f1
함수가 스택에 올라오며 생성된 Record는 더이상 참조되지 않으니 사라져야 하는게 맞다f1
함수가 실행되며 return하게된 익명함수가 전역에 있는 ff
란 변수를 통해 참조되고 있고 그 익명함수의 [[Envrionment]]
(함수가 <f.o>를 생성할 당시의 envrecord이기 때문에 f1
함수가 실행되며 생성되었다)가 f1
의 레코드를 참조하고 있기 때문에 G.C가 돌지 않아 계속해서 살아남아 있는 것이다ff()
는 그 <f.o>에 생성된 익명함수를 실행시키는 것이고 그 익명함수는 f1
함수의 레코드를 [[Environment]]
를 통해 참조하고 있으니 f1
함수의 레코드에서 i
를 찾아 연산하고 반환하게 되는 것이다이렇게 단순히 함수가 함수를 반환하는 것이 클로저가 아니라 이런 Function Object가 생성될 당시의 참조 Record등을 생각해서 이 Record 참조가 계속 유지 되는 것이 클로저이다.
각 책들에서 나오는 클로저에 대한 내용인데 한번 읽어보면 좋다
그럼 이 클로저를 이용해 어떤 걸 활용할 수 있냐면... 우리가 React를 배울 때 많이 했던 memoization 기능을 활용할 수 있다.
만약 우리가 클로저를 활용해 어떠한 값을 레코드 참조로 기억해두고 있다면 만약 다시 실행했을 때 그 값이 있거나 이미 실행했었다면 굳이 다시 코드를 전부 실행하는 것이 아닌 클로저 된 환경에서 해당 값을 찾으면 되는 것이다
메모이제이션 즉 메모하기, 기억해두는 것이다
const forFibonachi = () => {
const arr = [0, 1];
return (k) => {
if (arr.length > k) return arr.slice(0, k + 1);
for (let i = arr.length; i <= k; i++) {
arr[i] = arr[i - 2] + arr[i - 1];
}
return arr;
};
};
const fibo = forFibonachi();
피보나치 수열을 메모이제이션 하는 것인데
forFibonachi
가 return하는 함수가 있고 return되는 익명함수에 arr
을 클로저 시켜 저장하도록 했다
return된 익명함수는 피보나치 수열을 동작하지만 만약 내가 이미 한번 실행했던 피보나치 수열의 위치라면 for
반복문을 실행하지 않고 slice
를 활용해 해당 위치까지의 피보나치 수열을 반환한다.
고로 똑같은 값을 2번 실행하면 1번째는 반복문을 똑같이 실행하겠지만 2번째는 반복문을 실행하지도 않고 바로 답을 반환하여 시간,메모리 모두를 아낄 수 있다