JavaScript

[JavaScript] 클로저 (closure)_more

FRDYtheme 2022. 12. 7. 17:57

클로저 (closure)

함수와 함수가 선언된 어휘적 환경의 조합.

외부 함수의 지역 변수에 접근할 수 있는 함수의 환경.

 

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <title>클로저 closure 1</title>
    <style>
      .box {
        margin-top: 20px;
        width: 200px;
        height: 200px;
        background-color: lightpink;
      }
    </style>
  </head>
  <body>
    <button>click</button>
    <div class="box" id="box"></div>
    <script>
      const btn = document.body.querySelector("button");
      const box = document.body.querySelector("#box");

      const toggle = (function () {
        let state = false; // 내부 함수가 이 변수를 사용할 수 있음
        return function () {
          // 이 내부함수가 '클로저'이며 값을 외부 함수에 반환한다.
          box.style.display = state ? 'block' : 'none'; // 삼항연산자
          state = !state; // false면 true 대입
        };
      })();
      // btn.onclick = toggle
      btn.addEventListener("click", toggle); // btn을 클릭하면 toggle 함수 호출.
    </script>
  </body>
</html>
<script>
  function count1() {
    for (var i = 1; i <= 5; i++) {
      console.log(i);
    }
  }
  count1();
  
  console.log("비동기 함수 사용시 클로저 문제");
  function count2() {
    for (var i = 1; i <= 5; i++) {
      setTimeout(function () {
        console.log(i);
      }, 1000);
    }
  }
  count2();
  /* 
    i = 1일 때 setTimeout() 함수가 실행되나 1초 기다렸다가 콘솔 실행
    1초를 기다리는 동안 for반복문의 실행이 끝나기 때문에 i의 값은 마지막 i++가 끝난 6이고
    i의 값이 6이 된 후에 setTimeout()이 대기시간을 끝내고 console.log(i)를 실행하면서
    console.log(i) = 6을 5번 실행함.
  */

  console.log("즉시 실행 함수를 사용해 해결");
  function count3() {
    for (var i = 1; i <= 5; i++) {
      (function (count) {
        setTimeout(function () {
          console.log(count);
        }, 1000);
      })(i); // 즉시실행함수의 인수 i를 매개변수로 받아 변수값을 가진 상태로 대기하기 때문에 i를 순차적으로 출력.
    }
  }
  count3();

  function count4() {
    console.log('let을 이용한 해결');
    // 블록 레벨 스코프이기 때문에 반복문의 각 단계가 같은 변수 i를 공유하지 않음
    for (let i = 1; i <= 5; i++) {
      setTimeout(function () {
        console.log(i)
      }, 1000)
    }
  }
  count4();
</script>

변수의 유효 범위 지정 (Lexical scoping)