[JavaScript] ⭐️ for, settimeout, var, let

민승기·2023년 11월 3일
0

JavaScript

목록 보기
14/24
post-thumbnail

다음의 코드는 어떨 결과를 가져올까?

for (var i = 0; i < 5; ++i) {
    setTimeout(
        function () {
            console.log('variable-' + i);
        }, 100
    );
};

음 for문 내 비동기 함수가 실행되고 익명함수를 콜백 받고...
0~ 4가 출력되지 않을까 생각했다...

일단 답은 틀렸다. 사실 나는 이 코드를 보고 그냥 for문 돌리는거니까 0~4가 출력되겠지 안일하게 생각했었는데 어떻게 코드가 흘러가는지 알아보자.

for (var i = 0; i < 5; ++i) {
    setTimeout(
        function () {
            console.log('variable-' + i);
        }, 100
    );
};

// 결과: variable-5
//		variable-5
//		variable-5
//		variable-5
//		variable-5

실행순서

  1. 전역 컨텍스트가 생성되면서 전역변수 i = 0 으로 선언과 동시에 초기화가 된다.
  2. for문이 실행되고 실행될때마다 for문 컨텍스트가 생성된다.
  3. 반복문 내부의 settimeout함수가 실행된다.
  4. settimeout 함수는 비동기적으로 실행되어 브라우저 내부의 멀티스레드인 WebAPIs에 의해 처리가 된다.
  5. for문이 실행된다. 5번
  6. settimeout 함수 내부에서 사용된 익명함수는 클로저로써 상위 스코프에 접근이 가능하다.
  7. for문에서 정의된 i 변수에 접근이 가능하다.
  8. 이후 settimeout 실행컨텍스트가 생성되는데 이미 for문은 종료되어있다.
  9. for문이 종료되었을때 i 변수의 값은 5가 된다. i = 5;
  10. 이와같은 방법으로 5번 실행되고 variable-5 가 5번 한번에 출력된다.
  11. var의 경우에는 반복문이 실행될때마다 i변수의 값이 변경되지만
for (let i = 0; i < 5; ++i) {
    setTimeout(
        function () {
            console.log('variable-' + i);
        }, 100
    );
};

// 결과: variable-0
//		variable-1
//		variable-2
//		variable-3
//		variable-4
  1. varlet으로 변경하면 let의 경우에는 반복문이 실행될때마다 새로운 스코프를 생성하기 때문에
  2. i의 값이 독립적으로 유지되고 0~4까지의 값이 출력된다.

고민한 내용

  1. varlet의 차이점에 대해

    • var는 함수 스코프의 적용을 받는다.
    • let은 블록 스코프의 적용을 받는다.
    • let의 경우에는 for문 스코프의 적용을 받는다.
    • 따라서 for문이 실행될 때마다 새로운 변수 i=0, i=1, i=2... 각각의 스코프에 적용을 받이 때문에 다른 값을 출력한다.
  2. let 사용 외에 다른 해결방법은 없는가?

    • 위의 1번 내용과 같이 var는 함수 스코프의 적용을 받는다고 했다.

    • for문을 함수로 감싸면 어떨까?

    • function forLoop() {
      	for (var i = 0; i < 5; ++i) {
          	setTimeout(
                function () {
                    console.log('variable-' + i);
                 }, 100
              );
          };
      }
      forLoop();  // 결과: variable-5
      			//		variable-5
      			//		variable-5
      			//		variable-5
      			//		variable-5
      
    • 아 상관없다. 어짜피 for문 내에서만 사용하니까.

    • 그러면 for문 내에 settimeout 함수를 콜백함수로 적용시켜보자.

    • for (var i = 0; i < 5; ++i) {
      	const forLoop = function(j) {
      		setTimeout(function () {
      			console.log('variable-' + j);
      		}, 100);
          }
      	forLoop(i);
      }
      console.log(i);
          // 결과: 5
          //		variable-0
          //		variable-1
          //		variable-2
          //		variable-3
          //		variable-4
    • 값이 0~4로 변경되었다!

    • 변수값을 고정시키기 위해 j를 끌어다가 사용했다.

    • 전역변수 i의 값은 5다.

결론

  • letconst를 쓰자.
profile
개발자를 꿈꾸는 늙은이👨🏻‍💻

0개의 댓글