[멋사] js-var사용으로 인해 초래될 수 있는 문제

밥슌·2025년 4월 25일
0

☕❌js

목록 보기
13/15

"var은 함수 스코프를 가진다. 이것이 어떤 문제를 초래할 수 있는지 알아보자."

요구사항

문서내의 모든 버튼을 클릭했을때,
각각 "btn-0 클릭", "btn-1 클릭", "btn-2 클릭"
... "btn-n 클릭"을 콘솔에 출력하시오.

<script>
      window.onload = function () {
        const btns = document.querySelectorAll("button");
        // IIFE pattern
        for (var i = 0; i < btns.length; i++) {
          btns[i].addEventListener("click", function () {
            console.log(`btn-${num}클릭`);
          });
        }
      };
    </script>


위의 그림에서 알수 있듯이 var을 사용하면 원하는 결과를 얻을 수 없다.

왜 그런걸까?

  1. i = 0일 때, function() { console.log(i); } 함수를 배열에 저장.

  2. i = 1일 때도 또 함수 저장.

  3. i = 2일 때도 또 함수 저장.

그래서 funcs에는 함수가 3개 저장:

[
  function() { console.log(i); },
  function() { console.log(i); },
  function() { console.log(i); }
]

이 세 함수는 모두 같은 i를 바라보고 있다! (어매나)

현재 위 코드에서 i는 모든 함수들이 같이 보는 공용 메모장 같은 것
반복문은 메모장에 숫자 적으면서 함수들을 저장해두는 거고,
함수들은 "나중에 저 메모장에 적힌 거 보고 출력할게!" 라고 약속해놓은 상황.
근데 반복문이 끝나고 나면, 메모장에는 3만 써 있음. (var라는 놈이 이래서 문제다,,)
그래서 함수들이 실행될 때마다 3만 출력

<script>
      window.onload = function () {
        // 문서내의 모든 버튼을 클릭했을때
        // 각각 "btn-0 클릭", "btn-1 클릭", "btn-2 클릭"
        // ... "btn-n 클릭"을 콘솔에 출력하시오.
        const btns = document.querySelectorAll("button");
        // IIFE pattern
        for (var i = 0; i < btns.length; i++) {
          ((num) => {
            btns[i].addEventListener("click", function () {
              console.log(`btn-${num}클릭`);
            });
          })(i);
        }
      };
    </script>


이런 방식으로 해결할 수 있다.

하지만 지금은 2025년.

ECMA6의 시대.

우리는 let과 forEach를 사용함으로써 이를 해결할 수 있다.

	// ECMA5 forEach
    // Array.prototype.forEach: 배열의 각 요소를 순회하면서 지정한 콜백 함수를 실행
    // 콜백 함수는 첫번째 인자로 배열의 요소, 두번째 인자로 요소의 인덱스를 전달받는다.
    // [btn1, btn2, btn3].forEach((btn, i) => { });
    btns.forEach(function(btn, i){
      btn.addEventListener('click', function(){
        console.log(`btn-${i} 클릭`);
      });
    });
    // ECMA6 let
    for(let i=0; i<btns.length; i++){
      btns[i].addEventListener('click', function(){
        console.log(`btn-${i} 클릭`);
      });
		}
profile
마트 시식코너같은 저의 벨로그에 어서오세요.

0개의 댓글