ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [javascript] for문과 setTimeout
    개발공부 2023. 11. 14. 20:26

    자바스크립트에 내장된 메서드로 setTimeout이라는 기능이 있다

    setTimeout(function, milliseconds, parameter1, parameter2, ...)

     

    펑션으로 지정한 기능을 뒤에 지정한 시간(밀리초) 마다 작동하게 하는 기능이다.

     

    for(var i=0; i<3; i++){
        setTimeout(function() {
            alert(i);
        },1000);
    }

     

    그렇다면 이 코드는 어떤식으로 작동하는가?

    간단하게 보면, for문을 통해 '1초에는 0, 2초에는 1, 3초에는 2라고 알림창이 총 3번, 각 1초 간격으로 뜬다' 라는 결과가 나올것 같다.

     

    그러나 실제 결과는 그렇지 않다.

     

    https://jsbin.com/?html,js,output 사이트를 이용해 작동시킨 코드

     

     

    1초뒤에 3이 3번 연속으로 뜨고 종료된다.

    왜 코드를 단순히 봤을때 생각한 결과와 실제 결과가 다를까?

     

    1. for문의 동작 속도

    http://www.tipssoft.com/bulletin/board.php?bo_table=story&wr_id=56

     

    해당 테스트는 for문과 while문의 속도 차이를 비교하기 위한 글이지만, 해당 글에서 테스트 한 바와 같이

    (특별히 로직이 없지만) 1만번의 반복문이 도는시간이 setTimeout에서 지정한 1000ms보다 빠른것을 볼 수 있다.

    즉, setTimeout이 동작하기 전 이미 for문은 전부 다 끝난 상태로 i의 최종값인 3으로 alert(3)을 띄우게 되는 셈이다.

     

    2. var의 특성

     

    var와 let의 차이중 하나는 서로 다른 scope를 가지고 있다는 것이다.

    var는 함수 스코프로 for문의 선언문에서 선언해도, for문의 외부에서도 참조가 가능하다.

    let(과 const)는 블록 스코프로 선언된 함수/if문/for문/while문 등 에서만 유효한 변수이다.

    그렇기 때문에 위의 setTimeout을

     

    for(let i=0; i<3; i++){
        setTimeout(function() {
            alert(i);
        },1000);
    }

     

    var에서 let으로 바꿔서 이런식으로 사용하면 for문이 빠르게 돌지만, alert(0)/alert(1)/alert(2) 로 각각의 변수가 유지됨으로서 3번의 alert가 0,1,2로 나오게 된다.

    하지만, 위와 같은 방식으로도 for문의 동작속도 때문에 1초뒤에 0,1,2가 세번 연속으로 뜨고 종료될뿐이다.

    이를 해소하기 위해서는 setTimeout의 동작 속도를 변수인 i를 통해 늦춰 i * 1000을 사용해 느리게 한다면, 처음 생각한 

    1초마다 alert창이 뜨고 값이 변하는 결과를 얻을 수 있다.

     

    3. closure

     

    for(var i = 0; i < 3; i++){
        function closure(args) {
          setTimeout(function() {
            alert(args);
          }, i * 1000);
        }
      closure(i);
    }

     

    closure란 어떤 함수에서 선언한 변수를 참조하는 내부함수를 외부로 전달할 경우, 해당 환경을 기억해 그때의 변수가 사라지지 않는 것을 의미한다.

    즉, for문에서 각 i의 값을 기억했다가 사용하기 때문에 let이 아닌 var를 사용해도 위와 같은 결과를 얻을 수 있다.

    선언된 변수를 해당 for문 외에도 다른데서 사용해야 한다면 클로저를 활용하는 것 역시 하나의 방법일 수 있다.

     

     

     

    결론

     

    var, let처럼 자바스크립트 변수의 범위(scope)에 대해 생각하면서 범위에 맞게 선언해 사용해야 한다.

    또한, 클로저에 대해 간단하게 알 수 있는 기회였다.

    '개발공부' 카테고리의 다른 글

    github  (0) 2024.06.13
    메이븐  (0) 2024.06.13
    디자인 패턴  (0) 2023.06.26
    [프로그래머스] 콜라츠 추측 - java  (0) 2023.06.25
    TCP와 UDP의 특징과 차이점  (0) 2023.06.20
Designed by Tistory.