JS에서 변수를 var을 통해 선언하는 것과 let을 통해 선언하는 것의 차이 중, scope의 차이에 대해서 살펴보겠습니다.
먼저 var를 사용해서 문제를 겪었던 상황을 살펴보겠습니다.
function somefunction(){
for(i = 0 ; i < 3; i++){
var a = i;
var btn = createElement("button");
// i번째 버튼을 누르면 alert(i) (X)
// 전부 alert(2) (O)
btn.onclick = alert(a);
}
}
동적으로 버튼을 3개 만들고, 클릭 시 i번째 버튼이 alert(i)를 호출하는 의도로 작성한 코드이지만, 주석에 표현한 것처럼 실제 동작은 그렇지 않습니다.
원인부터 말하자면, var로 선언한 변수 a의 scope가 function scope 이므로 for문 안에서 var a = i;와 같이 선언하더라도 새로운 변수가 생성되는 것이 아니기 때문입니다.
여기서 function scope란 변수의 scope가 function 단위임을 의미합니다.
즉 3개의 버튼의 onclick에 전달된 변수 a는 모두 같은 변수(같은 메모리)이고, a에 마지막에 할당된 값이 2이므로 모두 alert(a) => alert(2) 를 호출하는 것입니다.
일반적으로 C나 JAVA 등에서 {}를 기준으로 scope가 나눠지는 것을 block scope라고 합니다.
해결법은 2가지가 있습니다.
function somefunction(){
for(i = 0 ; i < 3; i++){
(function(i){
var a = i;
var btn = createElement("button");
// i번째 버튼을 누르면 alert(i) (X)
// 전부 alert(2) (O)
btn.onclick = alert(a);
})(i);
}
}
즉시 실행 함수로 감싸면 매번 다른 함수로 실행되므로, var a 와 같이 실행하더라도 매번 반복마다 서로 다른 변수가 생성됩니다.
var 대신 let을 이용하면, 일반적인 언어와 같이 block scope를 따르므로, 처음에 의도한대로 동작합니다.