기초 스크립트 언어를 공부하던 중 발견하게 된 Declaring Block-Scoped 라는 단어를 발견하게 되었다.
이 글은 해당 단어의 의미를 파헤치며 알게 된 지식들을 정리한 것이다.
Declaring Block-Scoped 구글 번역기를 이용해 직역하자면 '블록 범위 선언'을 말한다.
Declaring Block-Scoped는 블록 범위 선언이라는 말 그대로 블록 범위에서만 효력을 나타내는 변수를 이야기한다. const와 let이 Declaring Block-Scoped Variables에 해당하며, 프로그램 전역에서 효력이 있는 Global object(전역 변수)와 대치된다.
javaScript tutorial(https://www.javascripttutorial.net/es6/javascript-let/)에서 제시한 예시를 통해서 더 자세하게 설명해보겠다.
for(var i = 0; i <5; i++){
setTimeout(function(){
console.log(i);
},1000);
}
위와같은 코드를 실행하면 우리는 console에 0 1 2 3 4가 차례로 출력될 것이라고 예상 할 수 있다.
5
5
5
5
5
그러나 실제로는 이와 같은 결과가 출력 된다.
이런식의 결과가 나오는 이유는 다음과 같다.

setTimeout은 설정된 시간 이후에 실행되도록 되어있기 때문에 호출 후 대기 상태가 되고 그 이전에 for문은 setTimeout을 다섯번 호출하고 i를 증감시킨 다음 모두 끝나게 된다.
때문에 setTimeout에 설정된 시간이 되었을때 이미 호출되어있던 setTimeout 다섯개가 한번에 실행이 되는데 변수가 var과 같은 전역 변수로 선언된 i의 값을 참조하기 때문에 루프가 끝난 뒤에 callback 함수인 setTimeout이 참조하는 i의 값은 5라서 5가 다섯번 출력이 되는 것이다.
예전에는 문제를 해결하기 위해서 다음과 같이 코드를 수정했다고 한다.
아래는 위의 코드에 IIFE pattern을 적용한 것이다.
for (var i = 0; i < 5; i++) {
(function (j) {
setTimeout(function () {
console.log(j);
}, 1000);
})(i);
}
패턴을 적용하고 난 뒤의 결과값은 아래와 같이 예상한 대로 잘 출력이 된다.
0
1
2
3
4
이와같은 결과가 나오는 이유는 다음과 같다.
function을 이용해 j의 값을 직접 대입해 주었기 때문이다.
후에 i의 값을 참조하도록 한 것이 아닌 for 문의 i의 값을 j로 setTimeout의 console.log안에 대입해서 넘겨줬기 때문에 후에 우리가 원하던 답으로 출력을 받을 수 있게 된다.

이것을 응용해서 이런식으로 코드를 수정할 수 있다.
for(var i = 0; i <5; i++){
setTimeout(function(){
console.log(i);
}, i * 1000);
}
이렇게 코드를 수정하고 나면 console에는 5가 다섯번 찍히지만 51000 이후에 모든 결과값이 동시에 찍히는 것이 아닌 순차적으로 11000, 21000, 31000 ... 5*1000 이렇게 시간적으로 텀을 두면서 결과값이 찍힌다.
값이 변한 전역변수를 나중에 참조하느냐, 값을 대입해서 호출하느냐의 차이였던 것이다.
아무튼 이 문제는 Block-Scoped 속성의 변수의 등장으로 function을 하나 더 추가하거나 기타등등 여러가지 방법을 구현하는 것 대신에 global object인 var을 Block-Scoped의 변수로 바꾸는 것 만으로 해결 할 수 있게 되었다.
for(let i = 0; i <5; i++){
setTimeout(function () {
console.log(i);
},10000);
}
결과
0
1
2
3
4
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined
https://www.javascripttutorial.net/es6/javascript-let/
es6문법을 최근에 공부하는데 포스팅이 참고가되었습니다. 감사합니다~