| 일 | 월 | 화 | 수 | 목 | 금 | 토 | 
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 
| 9 | 10 | 11 | 12 | 13 | 14 | 15 | 
| 16 | 17 | 18 | 19 | 20 | 21 | 22 | 
| 23 | 24 | 25 | 26 | 27 | 28 | 29 | 
| 30 | 
													Tags
													
											
												
												- Promise
 - React
 - 태그된 유니온
 - CORS
 - 인증/인가
 - async/await
 - dfs
 - Jest
 - 공변성
 - map
 - app router
 - recoil
 - 인터섹션
 - 결정 알고리즘
 - TS
 - 호이스팅
 - useAppDispatch
 - tailwind
 - 무한 스크롤
 - 리터럴 타입
 - webpack
 - CI/CD
 - 반공변성
 - autosize
 - MSA
 - 타입 좁히기
 - RTK Query
 - ESlint
 - SSR
 - 투포인터
 
													Archives
													
											
												
												- Today
 
- Total
 
짧은코딩
클로저 본문
반응형
    
    
    
  클로저
클로저란?
- 함수와 외부 변수와의 관계
 - 클로저란 내부 함수가 외부로 반환된 이후에도 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
반응형
    
    
    
  'JS > 인간 JS엔진' 카테고리의 다른 글
| await 연달아쓰면 Promise.allSettled를 생각해보자 (1) | 2024.01.29 | 
|---|---|
| async/await, Promise로 바꾸기 (1) | 2024.01.28 | 
| Promise에도 동기는 있다! (0) | 2024.01.27 | 
| 비동기는 동시가 아니다 (2) | 2024.01.27 | 
| Promise, async/await (2) | 2024.01.25 | 
			  Comments