클로저 실용적이고 쉬운 설명!!
클로저
- 클로저는 함수와 외부변수와의 관계이다.
- 클로저가 어려운게 클로저가 문제가 아니라 for문(반복문)과 비동기를 함께 사용하면 종종 발생한다.
- 해결방법으로는 2가지가 있다.
var
유지 => 즉시 실행함수로 클로저 생성 <== 이게 클로저를 활용해서 해결한 방법이다.var
=>let
클로저를 활용하지않고var
를let
으로 바꿔주어서 해결할 수 있다.
function a() {
for (var i = 0; i < 5; i++) {// 여기서 var 는 a()로 올라간다. i가 4일 때까지는 true인데, i가 5가 되고, 5 < 5가 false
setTimeout(() => {
console.log(i);
}, i * 1000);
}
}
a();
//5
//5
//5
//5
//5
우리는 원하는건 1초뒤에 0, 2초뒤에 1, 3초뒤에 2, 4초뒤에 3, 5초뒤에 4를 출력하고 싶은데 위에 코드를 돌려보면 1초, 2초, 3초, 4초, 5초뒤에도 모두 5가 출력된다.
그 이유는 위 코드에서 var
는 function a
스코프는 한개고, for
문의 스코프는 5개 a
스코프에서 i
는 0 에서 5가 되는거고, for문
의 스코프 5개에서는 i
는 각각 0, 1, 2, 3, 4가 된다.
- 즉시 실행 함수로 클로저 생성하기로 해결하면
function a() {
for (var i = 0; i < 5; i++) {
(function(j) { // 여기서 함수는 선언이자 호출
setTimeout(() => {
console.log(j); // 이렇게 하면 f(j)가 5번 반복되기 때문에
}, i* 1000);
})(i);
}
}
a();
//0
//1
//2
//3
//4
var
=>let
으로 바꿔주어서 해결하면
function a() {
for (let i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, i * 1000);
}
}
a();
//0
//1
//2
//3
//4
만약 cnt
라는 값은 무조건 cntPlus
으로만 바꾸고 싶은 경우를 구현해 보고 싶다고 한다면
무조건 이 함수가 실행 됐을 때만 1씩 증가시키도록 코드를 구현하는거다.
그런 코드를 짜고 싶으면 이런 식으로 짤 수 있을 것이다.
let cnt = 0;
function cntPlus() {
cnt = cnt + 1;
}
console.log(cnt); // 0
cntPlus();
console.log(cnt); // 1
// 만약에
// 1억개의 코드
cnt = 100;
// 1억개의 코드
cntPlus();
console.log(cnt); // 101
내가 가정한 상황은 이 cnt
라는 변수는 무조건 cntPlus
로만 값을 증가 시킬 수 있고 다른 걸로 바꾸면 안되는 그런 상황인데 이 중간에 cnt라는 변수가 접근 가능하기 때문에 내가 생각하는 상황을 완벽하게 구현 할 수 없다.
이런 상황을 해결하려면 변수를 접근 못 하게 해야한다.
이때 필요한게 “클로저” 이다.
일단 cnt
가 전역변수이기 때문에 cnt
를 지역변수로 바꿔 줘야 한다. 즉, 함수로 감싸준다.
이렇게 하면 밖에서 참조를 할 수 없게되지만 cntPlus를 실행시킬수 없다. 이때 cntPlus를 사용하려면 return을 사용해야한다. 이렇게 하면 cntPlus를 실행시킬 수 있지만 cnt자체를 출력시키고싶으면 어떻게 해야 할까?
function closure() {
let cnt = 0;
function cntPlus() {
cnt = cnt + 1;
}
return {
cntPlus,
}
}
const cntClosure = closure();
console.log(cntClosure); // { cntPlus: [Function: cntPlus] }
cntClosure.cntPlus();
이럴 땐 출력하는 함수 printCnt
를 만들면 된다. 이렇게 cnt
라는 값은 기타 다른 방법으로는 이 값을 절대 바꿀 수 없다. 이 변수에 접근하는 방법은 오직 cntPlus()
, printCnt()
말고는 없다. 이렇게 하면 위에서의 기능을 구현할 수 있다. 추가적인 기능이 필요 할때는 함수를 return
하는 방식으로 구현한다.
function closure() {
let cnt = 0;
function cntPlus() {
cnt = cnt + 1;
}
function printCnt() {
console.log(cnt);
}
return {
cntPlus,
printCnt,
}
}
const cntClosure = closure();
console.log(cntClosure); // { cntPlus: [Function: cntPlus] }
cntClosure.printCnt(); // 0
cntClosure.cntPlus();
cntClosure.printCnt(); // 1
참고: 제로초 강의
댓글남기기