보통 일정시간마다 특정 값을 출력하는 문구를 만들 때, setInterval() clearInterval() 메소드를 활용하여 구성하였던것 같다.
기존에 구성하던 로직)
var i = 1;
var timer = setInterval(function(){
if(i>5){
clearInterval(timer)
}else{
document.write(i+"<br/>");
i++;
}
}, 1000)
그러다 문득, 반복문인 for문 안에서 처리 할 수 없는지 궁금해졌다.
setInterval도 버리고 setTimeout으로 구성하여 봤다.
첫번째 도전)
for(i=1; i<6; i++){
setTimeout(function(){
document.write(i+"<br/>");
}, 1000);
}
1초마다 찍히는게 아닌 동시에 6이 찍혔다.
for문의 동작은 이미 끝났고 1초뒤에 동작하는 setTimeout 메소드가 5개가 동시에 동작한 것이다.
그래서 시간을 각각 별개로 쪼개어 보았다.
1초후... 2초후... 3초후...
두번째 도전)
for(i=1; i<6; i++){
setTimeout(function(){
document.write(i+"<br/>");
}, 1000*i);
}
이번에도 아쉽게 결과는 6만 5개가 찍혔지만, 1초 마다 6이 찍히는걸 볼 수 있었다.
for문의 동작이 끝나기전 값을 따로 처리 해줘야 할 것 같다.
이부분을 처리하기 위해선 자바스크립트의 클로저 개념이 필요하다.
세번째 도전)
for(i=1; i<6; i++){
(function(x){
setTimeout(function(){
document.write(x+"<br/>");
}, 1000*x);
})(i);
}
클로저란 간단하게 말하면 내부함수가 외부함수에 접근할 수 있는 것을 말한다.
기존에 동작시키던 방식은 setTimeout 함수가 i를 참조할때 for문에서 이미 5번 돌고 마지막에 ++된 값에 의해 6으로 처리되어 찍히고 있었던 것이다.
즉시발동함수로 setTimeout 메소드를 감싸고 찍고 싶었던 i의 값을 매개변수에 처리한다.
i의 값은 이제 즉시발동함수의 매개변수로 지역변수가 되기 때문에 별도의 값으로 처리 되고, setTimeout의 메소드내 함수는 외부 함수의 지역변수 'x'값을 가져와 document.write()로 값을 찍고 시간도 각각 별개의 시간으로 연산될 것이다.
그래도 이해가 잘 안된다면 콘솔 창에 찍은 결과값을 다시보자.
for(i=1; i<6; i++){
(function(x){
console.log("즉시발동함수 > i="+i+" x="+x)
setTimeout(function(){
console.log("setTimeout > i="+i+" x="+x)
}, 1000*x);
})(i);
}
빨간 네모안에 있는 콘솔창 값은 즉시발동함수에서 한번에 찍힌 결과이다.
처음 i는 1 매개변수로 처리된 x도 1이고 하나씩 차례대로 증가되는걸 볼 수 있고, 그 이후 setTimeout에서 처리된 값을 보면 i는 이미 for문으로 동작이 완료된 i의 값을 찍고 있기 때문에 계속 보이던 6의 값이 찍히고 있고 x는 클로저로 인하여 1부터 5까지 처리되고 있는 걸 볼 수 있다.
'WEB > Javascript' 카테고리의 다른 글
Javascript - for in 반복문을 사용하여 출력하기 (0) | 2019.09.08 |
---|---|
Javascript - 스톱워치(stopwatch) 만들기 (0) | 2019.09.08 |
Javascript - 함수(Function)를 사용하는 이유, 문법 (0) | 2019.09.08 |
Javascript - 달팽이 배열 생성하기(snail Array) (0) | 2019.09.08 |
Javascript - 입력받은 숫자를 순서대로 홀짝 별로 배열에 삽입하기 (0) | 2019.09.08 |