function foo() { { var bar = "AA" } console.log(bar); } foo();
>> "AA"
function foo() { { let bar = "AA" } console.log(bar); } foo();
>> Uncaught ReferenceError: bar is not defined
<!-- html --> ... <button id="btn0">btn0</button> <button id="btn1">btn1</button> <button id="btn2">btn2</button> ...
/*-- javascript --*/ var btns = [ document.getElementById("btn0"), document.getElementById("btn1"), document.getElementById("btn2"), ]; function setClick() { for (var i = 0; i < 3; i++) { btns[i].onclick = function () { console.log(i); }; } } setClick();
버튼 3개가 있고 해당 버튼을 클릭하면 그 버튼에 맞는 숫자를 콘솔로 출력해주는 코드가 있다.
브라우저에서 버튼 0, 1, 2 를 차례로 클릭해보면,
>> 3
>> 3
>> 3
모두 3이 출력된다. 이건 우리가 원하던 결과가 아니다.
왜 이런 결과가 나올까?
우리가 위 코드에서 setClick() 을 호출했을때, 콘솔에 출력할 i 값을 찾는 스코프 체인은 다음과 같다.
// 스코프 체인_(변수 i가 var로 선언됐을 경우)
console.log가 실행된 함수 내부 >>
setClick() 함수 내부
즉, var 는 함수단위로 호출된 값을 찾는다.
... function setClick() { for (var i = 0; i < 3; i++) { btns[i].onclick = function () { console.log(i); }; } // current i === 3 } setClick(); ...
때문에 위의 코드에서 console.log(i) 구문은 변수 i 탐색 과정에서 현재 실행 중인 for 루프문에서의 변수 i 값은 무시하고, setClick() 내부의 i값, 즉, setClick() 호출시에 스코프 생성 과정에서 한 차례 for루프를 끝낸 i 값, "i=3" 을 로그에 나타내게 된다.
우리는 누른 버튼의 순서에 대응하는 숫자를 콘솔로 출력하고 싶었다.
위 코드를 어떻게 고쳐야 할까?
... function setClick() { for (let i = 0; i < 3; i++) { btns[i].onclick = function () { console.log(i); }; } } ...
가장 간단한 정답은 "var 를 let 으로 바꾼다." 이다.
let 은 중괄호 {} 단위로 스코프 체인을 생성하며, 따라서 for 루프 내부의 i값을 콘솔에서 출력하게 된다.
// 스코프 체인_(변수 i가 let으로 선언됐을 경우)
console.log가 실행된 중괄호 내부 >>
for 루프문의 중괄호 내부
해결법은 생각보다 간단했다!
참고문서
참고영상