ABOUT ME

Today
Yesterday
Total
  • Modern JavaScript 클로저
    FrontEnd/JavaScript 2023. 1. 29. 13:26

     


     

    1. 클로저란 

     

     

     

    • excution context 에서 필요한 개념으로, 함수 선언시 렉시컬 환경 (어디에 함수를 선언하였는가, 외부/내부)의 조합을 의미
    • excution context 관점에서 innerFunc이 호출되면 context에 stack이 쌓이고 Variable Object와 Scope chain, this에 바인딩할 객체가 결정된다.
    • outerFunc의 Activation Object, 함수자신을 순차적으로 바인딩하며 scope chain이 바인딩한 객체가 렉시컬 스코프 범주의 개념이다.
    • 반환된 내부 함수가 자신이 선언되었을 때의 환경 (Lexical environment)인 스코프를 기억하여 자신이 선언되었을 때의 환경(스코프)밖에서 호출되어도 Lexical environment를 기억하는 함수 -> 스코프체인을 통해 참조
    • 상태 변경이나 가변데이터를 피하고 불변성을 지향하는 함수형 프로그래밍으로 부수효과를 최대한 억제하여 오류를 피함 (안정성)
    • 메모리 차원에서는 손해보는 환경

     

    function outerFunc() {
      var x = 10;
      var innerFunc = function () { console.log(x); };
      innerFunc();
    }
    
    outerFunc(); // 10
    

     

    * innerFunc 함수가 변수x 검색  --> 실패 --> outerFunc (활성객체) 에서 변수 x (자유변수) 검색 --> 성공 --> 반환 (콜스택, 실행 컨택스트에서 outerFunc 소멸)

    - 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부함수가 호출되어도 외부함수의 지역 변수에 접근할 수 있다.

     

     


     

    2. 클로저 활용

     

    • 상태유지 : 현상태를 기억하고 변경된 상태 유지

            - isShow (Lexical environment의 변수, 생성시 기억) : 클로저가 기억하는 변수

            - 이벤트 핸들러인 클로저를 제거하지 않는한 isShow는 소멸하지 않는다. (현상태 기억)

            - 버튼 클릭시 이벤트핸들러 클로저 호출

            - isShow값 변경 및 최신상태 유지 

     

    <!DOCTYPE html>
    <html>
    <body>
      <button class="toggle">toggle</button>
      <div class="box" style="width: 100px; height: 100px; background: red;"></div>
    
      <script>
        var box = document.querySelector('.box');
        var toggleBtn = document.querySelector('.toggle');
    
        var toggle = (function () {
          var isShow = false;
    
          // ① 클로저를 반환
          return function () {
            box.style.display = isShow ? 'block' : 'none';
            // ③ 상태 변경
            isShow = !isShow;
          };
        })();
    
        // ② 이벤트 프로퍼티에 클로저를 할당
        toggleBtn.onclick = toggle;
      </script>
    </body>
    </html>
    

     

    • 전역 변수 사용 억제

            - counter (전역변수) : 전역변수로 언제든 접근 및 변경 가능

            - increase (클로저) : 의도치 않게 값이 변경 되는 것을 방지 (자신이 생성됐을 때의 환경을 기억)

    <!DOCTYPE html>
    <html>
    <body>
      <p>전역 변수를 사용한 Counting</p>
      <button id="inclease">+</button>
      <p id="count">0</p>
      <script>
        var incleaseBtn = document.getElementById('inclease');
        var count = document.getElementById('count');
    
        // 카운트 상태를 유지하기 위한 전역 변수
        var counter = 0;
    
        function increase() {
          return ++counter;
        }
    
        incleaseBtn.onclick = function () {
          count.innerHTML = increase();
        };
      </script>
    </body>
    </html>
    

     

    • 정보의 은닉

            - public property : counter가 this에 바인딩된 프로퍼티라면 Counter는 외부에서 접근 가능

            - private 하게 사용 : 아래 예시는 Counter 내에서 선언된 변수 counter는 외부에서 접근 불가 

     

    function Counter() {
      // 카운트를 유지하기 위한 자유 변수
      var counter = 0;
    
      // 클로저
      this.increase = function () {
        return ++counter;
      };
    
      // 클로저
      this.decrease = function () {
        return --counter;
      };
    }
    
    const counter = new Counter();
    
    console.log(counter.increase()); // 1
    console.log(counter.decrease()); // 0
    

    'FrontEnd > JavaScript' 카테고리의 다른 글

    댓글

Designed by Tistory.