클로저문제 해결

홍요한·2020년 7월 1일
1

JavaScript

목록 보기
8/10
post-thumbnail

클로저

클로저 : 전역범위와 함수와의관계가 클로저 관계이다.

비동기와 반복문을 같이쓸 때 클로저 문제가 자주 발생한다.

클로저문제

[문제]

for(var i = 0; i < 100; i += 1){
	setTimeout(function(){
    	console.log(i);
      // 결과 i가 100인상태로 1초마다 100이 찍힘. 
	}, i * 1000)
}

위 코드에서 만들고 싶었던 내용은 0,1,2,3,4,5 ... 99가 찍히는 것이었다.
하지만 100,100,100,100 ... 100 이 찍히는 현상이 일어나고 있고 이 문제를 '클로저문제' 라고들 한다.

for문안에 있는 setTimeout은 '비동기' 이다. 그래서 코드를 위에서 아래로 읽는 javascript의 경우 컴퓨터의 처리속도가 빨라 for문은 이미 100까지 돌아가 있는 상태에서 setTimeout의 콜백안에있는 내용이 실행된다.

그래서 i * 1000의 i 는 0,1,2,3,4 ... 가 되는 반면 setTimeout의 콜백{} 안에있는 i 는 100이 된다.

더 정확히는 비동기의 콜백 안에있는 변수는 선언할때가 아니라 실행할 때 값을 찾는다.
즉, setTimeout 콜백{}안 i는 setTimeout이 실행될 때 값을 0,1,2초뒤에 찾기 때문에 i는 for문의 영향으로 100이 출력된다.
※0초일때 100이 출력되는 이유는 이벤트루프에 있다.

클로저해결

[해결]

for(var i = 0; i < 100; i += 1){ // 0일 때
	function 클로저(j){ // i값 -> j = 0;
		setTimeout(function(){
      		console.log(j) 
          	// 렉시컬스코프의 이유로 j = 0;
    	}, i * 1000); // i = 0;
	}클로저(i); // i = 0;
}

for문을 돌릴 때 i = 0이고, 클로저(0)을 실행한다. 클로저(j)는 i의 인자를 받아기때문에 0 이된다.

setTimeout의 콜백{}을 실행할 때 변수 j를 찾는다. 변수j는 스코프체인을 이루어 한단계 밖에 있는 클로저 j에서 0 을 가져온다.

따라서 실행은 1초마다 1,2,3,4, .. 99가 된다.

[참고자료]

클로저 let으로 해결

var 과 let의 차이

var는 함수 스코프에 해당되고,
let은 중괄호 스코프에 해당된다.

function x(){
  {
  	var t = 1;
  }
  console.log(t) // 1
}

function x(){
  {
  	let t = 1;
  }
  console.log(t) // error
}

var는 선언을 중괄호 안에 하고 실행을 중괄호밖에 해도 실행이 된다. 그 이유는 함수안에있기 때문이다.

반대로 let은 선언을 중괄호안에하고 실행을 밖에서 하면 실행이 되지 않는다. 그 이유는 let은 현재 중괄호안에 묶여있기 때문이다. 그래서 console.log(t)를 중괄호 안에 넣어주면 실행이 된다.

[참고자료]

0개의 댓글