Week 1 - 오피스아워

jplendor·2022년 8월 12일
0

카운터 변수 i를 var로 선언한 경우

for (var i = 1; i < 6; i++) {
  setTimeout(function timer() {
    console.log(i);
  }, i * 1000);
}

아래와 같이 for문과 같은 범위에 선언한 것과 같다.

var i = 1;
for (...) {
  setTimeout(function timer() {
    console.log(i);
  }, i * 1000);
}

5개의 timer() 함수는 선언할 당시 주변 환경인 전역 EC가 관리하는 변수 i (동일한 변수 i)를 사용하므로, 아래와 같은 결과가 나온다.
6
6
6
6
6

카운터 변수 i를 let으로 선언한 경우

for (let i = 1; i < 6; i++) {
  setTimeout(function timer() {
    console.log(i);
  }, i * 1000);
}

아래와 같이 for문 안의 지역 변수로 선언한 것과 같다.

for (...) {
  let i = 1
  setTimeout(function timer() {
    console.log(i);
  }, i * 1000);
}

for (...) {
  let i = 2
  setTimeout(function timer() {
    console.log(i);
  }, i * 1000);
}

for (...) {
  let i = 3
  setTimeout(function timer() {
    console.log(i);
  }, i * 1000);
}

...

5개의 timer() 함수는 for문 블록마다 관리되는 서로 다른 변수 i를 사용하므로, 아래와 같은 결과가 나온다.
1
2
3
4
5

미션!
var 키워드를 사용하면서 1 2 3 4 5 나오게 하기!

방법 1) 클로저 이용하기

makeTimer 함수를 통해 timer 함수를 생성한다.
makeTimer 함수는 변수 i를 받고, makeTimer 함수 실행 컨텍스트 안에서 관리한다.
그리고 timer 함수는 이 안에서 생성되기 때문에, 해당 i를 참조하게 된다.
i가 1, 2, 3, 4, 5일 때 각각 다른 makeTimer 함수 실행 컨텍스트가 생성되고 그 안에서 timer 함수가 생성되므로, 서로 다른 변수 i에 접근하게 된다는 아이디어로 작성했다.

const makeTimer = function (i) {
  return function timer() {
    console.log(i);
  };
};

for (var i = 1; i < 6; i++) {
  setTimeout(makeTimer(i), i * 1000);
}

방법 2) 즉시실행함수 이용하기

함수가 실행되면 실행 컨텍스트가 생긴다. 그러므로 즉시실행함수로 한번 감싸고, 인자로 i를 넘겨주면, 즉시실행함수 실행 컨텍스트 생기고, 그 안에서 변수 i가 관리된다.

for (var i = 1; i < 6; i++) {
  (function (i) {
    setTimeout(function timer() {
      console.log(i);
    }, i * 1000);
  })(i);
}
profile
만들기는 재밌어!

0개의 댓글