자바스크립트 클로저 공부하다가 유명한 함정에 걸린 것 같은데 원인을 정확히 모르겠어서 질문드려요.


0부터 4까지 1초 간격으로 찍고 싶어서 이렇게 짰거든요.


for (var i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i);
  }, i * 1000);
}


당연히 0, 1, 2, 3, 4 나올 줄 알았는데 실제로는 5가 다섯 번 찍혀요. 처음엔 오타인 줄 알고 몇 번을 다시 봤는데 계속 그러네요.


인터넷 찾아보니까 var 때문이라는 말도 있고 클로저 때문이라는 말도 있는데, setTimeout 콜백이 나중에 실행될 때는 이미 반복문이 다 끝나서 i가 5가 돼 있다 뭐 그런 설명이더라고요. 근데 왜 각 콜백이 자기 시점의 i를 기억 못 하는 건지가 잘 안 와닿아요.


그리고 var를 let으로만 바꿔도 0 1 2 3 4 제대로 나온다는데, 그게 왜 되는 건가요? let이 반복마다 새 변수를 만든다는 게 무슨 뜻인지, 예전 방식대로 즉시실행함수(IIFE) 같은 걸로 푸는 방법이랑 뭐가 다른지도 같이 알려주시면 감사하겠습니다.