티스토리 뷰

반응형

클로저

외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이러한 중첩 함수를 클로저라 한다.


📌

const x = 1;

// ①
function outer() {
  const x = 10;
  const inner = function () { console.log(x); }; // ②
  return inner;
}

// outer 함수를 호출하면 중첩 함수 inner를 반환한다.
// 그리고 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거된다.
const innerFunc = outer(); // ③
innerFunc(); // ④ 10

위 예시 코드를 보면 outer() 함수는 inner() 함수를 반환(return)하고 생을 마감한다. 그런데 함수를 돌려보면 10을 출력한다. outer() 함수는 생을 마감했는데 outer()의 지역 변수 x의 값 10이 어떻게 나오는 것일까?

 

여기서 다시 한번 클로저의 정의를 보자!

 

 


외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이러한 중첩 함수를 클로저라 한다.


 

 

 

함수는 자신의 상위 스코프를 기억한다. 위 예시 코드에서 inner() 함수는 outer() 함수의 렉시컬 환경을 상위 스코프로서 저장한다.

 

 

🔎 렉시컬 환경이란?

렉시컬 환경은 특정 코드가 작성, 선언된 환경을 의미한다.

 

 

outer() 함수가 끝나면 outer() 함수의 생은 마감하여 실행 컨텍스트 스택에서 제거되지만 outer() 함수의 렉시컬 환경까지 소멸하는 것은 아니다. outer() 함수의 렉시컬 환경은 inner() 함수가 참조하고 있고, inner() 함수는 전역 변수 innerFunc에 의해 참조되고 있으므로 가비지 컬렉션의 대상이 되지 않는다.

 

🔎 가비지 컬렉터

가비지 컬렉터는 누군가 참조하고 있는 메모리 공간을 함부로 해제하지 않는다.

 

📌 자유 변수

클로저에 의해 참조되는 상위 스코프 변수를 자유 변수라고 부른다.

 

 

 

마지막으로 정리하자면 클로저는 ① 상위 스코프 식별자를 참조하고, ② 외부 함수보다 더 오래 유지되는 경우의 중첩 함수를 말한다. ①번②번 둘 중 하나라도 성립되지 않는다면 클로저가 아니다.

 


클로저의 활용

클로저는 상태를 안전하게 변경하고 유지하기 위해 사용한다. 다시 말해, 상태가 의도치 않게 변경되지 않도록 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하기 위해 사용한다.

// 카운트 상태 변경 함수
const increase = (function () {
  // 카운트 상태 변수
  let num = 0;

  // 클로저
  return function () {
    // 카운트 상태를 1만큼 증가 시킨다.
    return ++num;
  };
}());

console.log(increase()); // 1
console.log(increase()); // 2
console.log(increase()); // 3

위 예시 코드는 클로저를 활용한 카운트 상태 변경 함수이다.

 

만약 변수 num이 전역 변수로 선언되면 언제든지 누구나 접근이 가능하여 변경도 누구나 가능하다. 그렇지만 클로저를 활용하면 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용한다.

 

 

 

좋아요는 로그인하지 않아도 누를 수 있습니다!

 

728x90
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함