var와 let의 차이, var의 클로저 이슈

Kim June Jae·2020년 9월 25일
0

javascript

목록 보기
1/1
post-thumbnail

varlet 의 차이

var 는 함수 단위로 수행된다.

function foo() {
  {
    var bar = "AA"
  }
  console.log(bar);
}

foo();

>> "AA"

let 은 {} 중괄호 단위로 수행된다.

function foo() {
  {
    let bar = "AA"
  }
  console.log(bar);
}

foo();

>> Uncaught ReferenceError: bar is not defined



var클로저 관련 대표적 이슈

<!-- 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);
    };
  } 
}
...

가장 간단한 정답은 "varlet 으로 바꾼다." 이다.

let 은 중괄호 {} 단위로 스코프 체인을 생성하며, 따라서 for 루프 내부의 i값을 콘솔에서 출력하게 된다.

// 스코프 체인_(변수 i가 let으로 선언됐을 경우)

console.log가 실행된 중괄호 내부 >>
for 루프문의 중괄호 내부

해결법은 생각보다 간단했다!



참고문서

MDN_클로저

참고영상

Youtube코드종_자바스크립트 대표적 클로저 실수를 let으로 해결?

profile
풀스택을 목표로 하는 학생 개발자입니다.

0개의 댓글