반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

클로저 본문

JS/인간 JS엔진

클로저

5_hyun 2024. 1. 30. 00:03

클로저

클로저란?

  • 함수와 외부 변수와의 관계
  • 클로저란 내부 함수가 외부로 반환된 이후에도 life-cycle 이 유지되는 것
  • 클로저 안에 정의된 함수는 만들어진 환경을 기억

클로저가 어려운 이유

  • 스코프, 비동기, var 등이 모두 섞여있다.
  • 클로저가 문제가 아니라, 클로저를 사용해서 해결하는 문제가 대부분이다.
  • 주로 for문(반복문)과 비동기를 함께 사용하면 종종 발생

예시

var을 한 경우

function a() {
  for (var i = 0; i < 5; i++) { // i가 4일때까지는 true, i가 5가 되고 5 < 5 false
    setTimeout(() => {
      console.log(i);
    }, i * 1000); // 0, 1000, 2000, 3000, 4000
  }
}
a();

-결과

 

-문제점

  • var과 for과 비동기가 섞여있다.
  • 해결법 1
    • var 유지 -> 즉시 실행 함수로 클로저 생성
  • 해결법 2
    • var -> let으로

-분석

  • for에서 var을 사용하면 특이하게 상위 스코프에 변수가 들어가게 된다.
    • 따라서 i가 a의 스코프에 있다.
  • for 문을 돌면서 i가 증가하고, i가 5가 되면 코드의 실행이 종료된다.
  • for 문이 돌면서 setTimeout은 비동기니까 콜백 함수가 백그라운드로 넘어간다.
    • 특이하게 setTimeout의 시간 부분은 잘 돌아간다.
  • 사진은 함수 a의 동기 부분이 모두 실행되고 난 상태이다.
  • 이제 비동기 부분이 실행되는데 i가 5가 되어있어서 출력 결과가 모두 5가 나오게 된다.
  • 결론
    • function a의 스코프는 1개, 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);
      }, i * 1000); // 0, 1000, 2000, 3000, 4000
    })(i);
  }
}
a();

 

-결과

 

-분석

  • 이 코드에서는 즉시 실행 함수를 사용하여 해결했다.
    • 즉시 실행 함수는 선언이자 호출이다.
  • 이 코드에도 for 문은 var이 있어서 일단 상위 스코프인 a에 i가 선언된다.
  • for 문 안에 즉시 실행 함수가 있어서 스코프가 나눠지게 된다.
    • 그렇기에 j의 값이 다른 함수 스코프가 생긴다.
    • 즉시 실행 함수의 i를 j로 고정시켰다.
    • setTimeout의 콜백 함수에서는 각각 다른 형제 스코프에 접근하기에 j의 값이 달라지게 할 수 있다.
  • 이 그림도 동기 부분까지만 실행한 상태이다.
  • 클로저
    • 즉시 실행함수와 for문이 클로저 관계이다.
    • setTimeout의 콜백 함수와 즉시 실행 함수의 j(외부 변수)가 클로저 관계이다.

let을 사용한 방법

function a() {
  for (let i = 0; i < 5; i++) {
    setTimeout(() => {
      console.log(i);
    }, i * 1000);
  }
}
a();

-결과

 

-분석

  • for 문에서 let으로 사용하면 i의 선언이 for 문 안에 된다.
    • i = 5가 되면 더 이상 코드가 실행되지 않는다.
  • 따라서 for문의 형제 스코프들이 같은 i를 사용하기에 결과가 잘 나오는 것을 알 수 있다.

-출처

https://www.youtube.com/watch?v=4hhlfq3Uy6U&list=PLcqDmjxt30Rt9wmSlw1u6sBYr-aZmpNB3&index=18

 

728x90
반응형

'JS > 인간 JS엔진' 카테고리의 다른 글

await 연달아쓰면 Promise.allSettled를 생각해보자  (0) 2024.01.29
async/await, Promise로 바꾸기  (1) 2024.01.28
Promise에도 동기는 있다!  (0) 2024.01.27
비동기는 동시가 아니다  (1) 2024.01.27
Promise, async/await  (2) 2024.01.25
Comments