[JavaScript] block-level scope란 (let vs var)
글의 목적
JavaScript의 block-level scope란 무엇인지 구체적인 사례를 통해 이해한다.
block-level scope의 존재를 알게 된 사례
React로 간단한 Todo-list 앱을 제작하고 있었다. 각 행마다 내용과 완료 버튼이 있는데, 이 때 이 완료 버튼 클릭 시 호출하는 함수인 'handleDone'에 관한 고민이 있었다.
quests.map((quest, i) => (
<QuestRow
key={i}
quest={quest}
handleDone={() => {
handleDone(i);
}}
handleDelete={() => {
handleDelete(i);
}}
/>
));
map을 사용하여 각 Todo 항목마다 한 행을 담당하는 Component를 뱉도록 한 코드이다. 그런데 여기서 () => handleDone(i)
의 i
가... 어떻게 살아있는거지...? 어떤 값을 참조하는거지? 하는 의문이 들었다.
실험1
let funcs = [];
let a = 1;
while (a <= 4) {
funcs.push(() => console.log(a));
a++;
}
for (const f of funcs) f();
위 코드의 실행 결과로 1, 2, 3, 4를 예상했지만... 5, 5, 5, 5 였다. 그렇다. 어찌보면 당연하다. f를 호출하는 시점에서 각 f가 참조하는 변수 a의 값은... 5이니까...! 그런데 저 위의 react 코드는 어떻게 각 i를 기억?하는 것일까?
실험2
let funcs = [];
let a = 1;
while (a <= 4) {
let local_a = a;
funcs.push(() => console.log(local_a));
a++;
}
for (const f of funcs) f();
여기서 local_a라는, block 내에서 let 키워드로 선언한 변수에 a값을 넣어주고, 각 f가 local_a를 참조하게 하면...! 1, 2, 3, 4를 출력하는 것을 볼 수 있다! local_a는 각 loop의 block에서만 유효한 변수이기에 이렇게 동작하는 것이다. 추가로, 각 block 내에서 선언된 변수들은 (참조되고 있는 한) 메모리에 계속 남아있는 다는 것을 알 수 있었다.
- local_a를 let이 아닌 var로 선언해줄 경우, global 변수가 되어 다시 5, 5, 5, 5를 출력하게 된다.
결론
간단한 실험을 통해 block-level scope가 무엇인지 이해할 수 있었다. 또한 let과 var의 scope 차이 또한 알게 되었다.