본문 바로가기

공부/javascript

javascript 심화 7 (클로저)

반응형

 

클로저 📖

1. 개념

`클로저`는 함수와 그 함수가 선언된 렉시컬 환경의 조합입니다.

 

2. 렉시컬 스코프

어디서 `호출했는지`가 아니라 어디에 `선언`했는지에 따라서 상위 스코프가 결정되는 것입니다!

const x = 1;

function foo() {
  const x = 10;
  bar();
}

function bar() {
  console.log(x);
}

foo(); // 1
bar(); // 1

 

bar 함수는 foo 함수 내부에서 `호출`됐지만 전역에서 `선언`되었기 때문에 전역변수 x를 참조하게 돼서 1을 출력하게 됩니다!

 

3. 함수가 선언된 렉시컬 환경

간단하게 설명하면 `클로저`란 부 함수의 변수에 접근할 수 있는 내부 함수입니다!

function outerFunc() {
  // 외부 함수의 변수
  var x = 10;

  // 내부 함수에서 외부 함수의 변수에 접근할 수 있습니다.
  var innerFunc = function () {
    console.log(x);
  };

  return innerFunc;
}

var inner = outerFunc();
inner(); // 10

 

outerFunc()는 내부함수 innerFunc()를 반환하고 종료되면서 콜스택에서 제거가 됩니다. 그래서 생명 주기가 끝난 것 같지만, inner() 함수를 호출하면 innerFunc()가 실행되면서 변수 x의 값인 10이 출력이 됩니다

 

왜 변수 x값이 10으로 출력이 될까요

 

innerFunc는 선언된 당시의 환경(=outer)을 기억하고 있기 때문에 변수 x의 값인 10을 출력하게 되는겁니다! 이와 같이 생명 주기가 끝난 외부 함수의 변수에 접근할 수 있는 함수를 `클로저`라고 합니다!

 

 

순서

  • 1. outerFunc 함수를 호출하면 innerFunc를 반환
  • 2. outerFunc 함수는 콜스택에서 제거
  • 3. innerFunc 함수는 런타임에 평가
  • 4. innerFunc 함수가 inner에 전달되었는데, outerFunc 함수의 렉시컬 환경을 여전히 참조하고 있음
  • 5. 콜스택에선 제거가 됐지만 outerFunc 함수의 렉시컬 환경까지 없어지는 것은 아님

 

outer, 렉시컬 환경이 궁금하시다면

 

javascript 심화 1 (실행 컨텍스트)

실행 컨텍스트 📖실행할 코드에 대한 `환경 정보`들을 모아놓은 `객체`입니다. 이렇게만 말하면 이해가 잘 안 될 것 같으니 더 자세하게 설명해 드리겠습니다. 우선 실행 컨텍스트를 이해하기

mingos-habitat.tistory.com

 

 

클로저를 왜 사용할까? 📖

1. 상태 유지

현재 상태를 기억하고 최신 상태를 유지하기 위해 사용합니다.

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

  // 클로저
  return function () {
    return ++num;
  };
})();

// 이전 상태값을 유지
console.log(increase()); //1
console.log(increase()); //2
console.log(increase()); //3

 

`클로저`는 상태가 의도치 않게 변경되지 않도록 안전하게 은닉하기 위해서 사용합니다

 

2. 캡슐화와 정보 은닉

`캡슐화`란 프로퍼티와 메서드를 하나로 묶는 것입니다.

객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용 가능합니다. 가지고 있는 정보가 예민하고 민감해서 정보 은닉이 필요한 경우에 사용합니다.

 

주의할 점 📖

1. 메모리 관리

클로저에 의해 외부 함수의 변수를 참조하고 있기 때문에 외부 함수의 생명 주기가 끝났음에도 가비지 콜렉터에 의해 메모리가 해제되지 않습니다.

 

2. 해결 방법

클로저를 할당한 변수에 null을 할당해줌으로써 메모리를 해제시키는 방법이 있습니다.

 

그러나 클로저는 개발자가 의도적으로 참조를 만들어서 사용하는 것이기 때문에 null을 할당하는 것이 오히려 유지보수 측면에서 좋지 않을 수 있습니다.

 

그래서 단점을 파악하고 사용해야 더 잘 활용할 수 있다고 생각합니다!

 

 

요약 📖

  • 클로저란 외부 함수의 변수에 접근할 수 있는 내부 함수
    • 선언된 당시의 환경(=outer)을 기억하기 때문에 생명 주기가 끝난 외부 함수의 변수에 접근 가능
  • 렉시컬 스코프란 호출이 아닌 어디에 선언 했는지에 따라 상위 스코프가 결정되는 것
  • 클로저를 사용하는 이유?
    • 상태 유지 : 상태가 의도치 않게 변경되는 걸 막기 위해서
    • 정보 은닉 : 가지고 있는 정보가 예민하고 민감할 때 사용 가능
  • 주의할 점
    • 가비지 콜렉터에 의해 메모리가 해제 되지 않기 때문에 단점을 파악해서 잘 활용해야 함.

 


출처 🏷️

https://enjoydev.life/blog/javascript/6-closure

반응형