클로저(Closer)

posinity·2023년 2월 24일
0

JavaScript

목록 보기
21/31

정의

번역하면 "폐쇄"
상위 스코프의 변수를 가르키는 함수이며, 클로저가 만들어진 환경을 기억

클로저는 함수다!


왜 다 5가 나오는가?
var는 함수 스코프를 따른다.
i는 전역 스코프에 등록됌.
setTimeout은 비동기단으로 이동
그 중에 for문이 계속 돌아가기때문에 i가 0,1,2,3,4,5가 됌.
싱글쓰레드기 때문에 setTimeout이 다 끝나더라도 큐에 남음
for가 다 끝난 후 setTimeout이 실행되고, 함수안에 i가 없으므로 상위로 이동.
i는 5기 때문에 모두 5가 나오는 것임

사용처

상태유지

클로저가 가장 유용하게 쓰이는 상황 중 하나는 현재 상태를 기억하고 있다가 상태가 변경되면 그것을 최신상태로 유지하는 것이다.

<!DOCTYPE html>
<html>
<body>
  <button class="toggle">toggle button</button>
  <div class="txt">
    <h1>toggle test</h1>
  </div>

  <script>
    let txtField = document.querySelector('.txt');
    let toggleBtn = document.querySelector('.toggle');

    let toggle = (function () {
      let isVisable = false;

      // 1.클로저를 반환
      return function () {
        txtField .style.display = isVisable ? 'block' : 'none';
        // 3. 상태 변경
        isVisable = !isVisable;
      };
    })();

    // 2. 이벤트 프로퍼티에 클로저를 할당
    toggleBtn.onclick = toggle;
  </script>
</body>
</html>

위의 예제는 간단하게 toggle 버튼을 통해 텍스트가 보였다가 안보였다가하는 예제인데,
결과는 아래처럼 나온다.

위의 코드에서 보면

1.즉시 실행함수가 있는데 이는 함수를 반환한 뒤 바로 소멸된다. 이때 반환된 힘수는 자신이 생성됐을때의 Lexical 환경에 속한 변수인 isVisable을 기억하는 클로저가 된다. 클로저가 기억하는 변수인 isVisable은 txt 표시 상태를 나타낸다.
2.클로저를 버튼 이벤트 프로퍼티에 할당을 했다. 이제 이 클로저를 제거하지 않는한 isVisable 은 소멸되지 않는다.
3. 버튼 클릭시 클로저가 호출되게되는데 이때 txt요소의 표시 상태를 나타내는 변수인 isVisable 값이 변경이 되게 된다. 이 변수는 클로저에 의해 참조 되고 있기 때문에 변경된 최신 값을 계속 유지할 수가 있다.

데이터 은닉화

보통 프로그래밍 초보자들은 전역변수를 통해서 공유될 변수를 작성하는데, 이렇게하면 오류가 발생할 확률이 매우 높아지게 된다. 그 이유는 누구든 이 전역변수에 접근할 수 있기 때문에 의도치 않게 값이 변경될 여지가 많다. 이는 심각한 장애로 이어질 수도 있다.

클로저를 이용하면 이러한 문제를 단번에 해결할 수가 있다.

<!DOCTYPE html>
<html>
  <body>
  <button id="plus">+</button>
  <p id="count">0</p>
  <script>
    let plusBtn = document.getElementById('plus');
    let countTxt = document.getElementById('count');

    let plus= (function () {
      // 카운트 상태를 유지하기 위한 자유 변수
      let count = 0;
      // 클로저를 반환
      return function () {
        return count++;
      };
    }());

    plusBtn.onclick = function () {
      countTxt .innerHTML = plus();
    };
  </script>
</body>
</html>

위의 예시는 숫자를 하나씩 카운트하는 코드인데, 여기서 count라는 변수가 만약 전역변수로 선언되어서 카운팅되게 만들어졌다면 이는 굉장히 위험한 프로그램이 될 것이다.

그런데 위처럼 클로저를 이용해 내부로 철저히 숨김으로써 데이터를 은닉화 시켰다.
객체지향 언어에서 private키워드를 이용해 캡슐화 시키는 것처럼 javascript에서도 클로저의 특징을 이용해 비슷한 기능을 구현할 수 있는 것이다.

참고자료

[클로저] 상위 스코프를 기억하는 함수..?

profile
문제를 해결하고 가치를 제공합니다

0개의 댓글