아래와 같은 코드의 출력이 어떻게 될까?
for (var i = 0 ; i < 3 ; i++) {
setTimeout(() => {
console.log(i)
}, 1000)
}
난 보고.. 1초 있다가 1, 또 1초 있다가 2, 또 1초있다가 3 찍힐거라고 생각했다.
정답은 1초 후 거의 동시에 3이 3번 찍힌다.
정답을 보고서, 아.. for문이 너무 빨리 돌아서 그렇구나? 1초안에 3번 도는게 끝나서 3이 세번 찍히는구나 했다.
그리고 await가 걸린것도 아니니 당연히 각 setTimeout은 거의 동시에 실행되니까,
그래서 거의 동시에 찍히는거구나 했다. (이건 당연한건데 왜 생각을 못했을까?)
그러면 for문 반복횟수를 늘리고, setTimeout 시간을 줄이면 다른 숫자도 찍히겠구나?
for (var i = 0 ; i < 10000 ; i++) {
setTimeout(() => {
console.log(i)
}, 10)
}
// 10000이 만 번 찍힘
아니었다.
음.. 스코프 때문인가? var를 let으로 바꾸면 1, 2, 3, ... 이렇게 찍히기 때문이다.
결론은 시간이나 횟수와는 상관이 없다. 백만번이건 천만번이건..
for (var i = 0 ; i < 10000 ; i++) {
console.log('a', i)
setTimeout(() => {
console.log('b', i)
}, 10)
}
이렇게 찍어보면 a 1 a 2 a 3 a 4.... 다 찍히고 나서 b 10000 만번 찍힌다.
이벤트루프에서 setTimeout은 console 찍고나서 실행할 여유가 생기기 때문에 다음 틱에 실행된다.
그래서 어떻게 하건 for문이 다 돈 뒤에 찍히는 것이다.
let은 순서대로 찍히는 이유는, 스코프가 블록에 있기 때문이다.
for문 내부에 변수가 있는것이나 다름이 없기 때문에.. 블록 스코프의 i를 참조하게 되어서 그렇다.
for (var i = 0 ; i < 10000 ; i++) {
const j = i;
setTimeout(() => {
console.log('b', j)
}, 10)
}
위 코드도 let을 쓴것과 같은 결과가 나온다.
아니면 내부에 클로저가 있는거랑도 결과는 같다.
반대로 var는 아래와 결과가 같다. 블록 밖의 변수를 사용했기 때문!
let i = 0;
for (i ; i < 10000 ; i++) {
setTimeout(() => {
console.log('a', i)
}, 10)
}
'Web development > Node.js & Typescript' 카테고리의 다른 글
package-lock.json의 역할과 커밋해야 하는 이유 (0) | 2020.04.03 |
---|---|
[Javascript] 이벤트루프와 호출 스택(call stack), 비동기성 (0) | 2020.04.03 |
[Javascript] map vs filter vs reduce (0) | 2020.02.11 |
[Javascript] List/Set/ Map 순회하기 (0) | 2020.02.09 |
[Javascript] 함수와 일급객체, 고차함수와 클로저 (0) | 2020.02.06 |
댓글