[24] 클로저

반응형

클로저란?

MDN 에서의 클로저의 정의는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이라고 나와있다

이게 도대체 무슨말인가?? 이를 이해하기위해서는 함수가 선언된 렉시컬 환경 을 이해해야할것이다.

자바스크립트는 렉시컬 스코프를 따르는 프로그래밍 언어인데 함수를 어디서 호출했느냐 가 중요한게 아니라 함수를 어디에 정의했는지에 따라 상위 스코프를 결정하는것이다.

const x = 1 ;

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

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

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

결국 상위 스코프는 렉시컬환경에서 자신의 외부 렉시컬 환경 정보를 저장하는

outer lexical Environment Reference 를 통해서 상위 렉시컬환경과 연결된다.

렉시컬 스코프를 알아봤다면 이를통한 진짜 클로저란 무엇인가?

const x = 1;

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

const innerFunc = outer();
innerFunc(); // 10

위의 코드를 보며 설명하자면

outer() 함수를 실행시키는 라인에서 inner 라는 리턴값을 반환하고 생명주기가 종료된다.

종료됬다는건? 실행 컨텍스트에 스택에서 제거가된다는 말이다.

이때 outer의 실행 컨텍스트가 제거됬음으로 더이상 outer 지역변수의 x 값은 유효하지않고 접근할수있는 방법이 없어보인다.

그러나 결과는 innnerFunc 의 값은 10을 반환하게된다.

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

한마디로 정리하자면 이미 생명주기가 종료된 외부함수의 “변수를 참조”할수있는 중첩함수를 클로저라 부른다.

좀더 자세한 설명을 하자면 outer 함수의 실행컨텍스트가 제거될때 렉시컬 환경까지 소멸하는것이 아니다.

왜냐면 가비지컬렉터의 알고리즘은 참조하고있지않은 것들을 선별해서 없앤다. 다만 ? outer함수의 렉시컬 환경은 inner 함수의 렉시컬환경 내부슬롯에 의해 참조되고있고

inner 함수는 전역변수 innerFunc 에 의해 참조되고있어 가비지 컬렉션의 대상이 되지않는다.

클로저의 활용

클로저는 상태를 안전하게 변경하고 유지하기 위해 사용한다.

const increase = (function () {
  let num = 0;

  return function () {
    return ++num;
  };
})();

console.log(increase());
console.log(increase());
console.log(increase());
console.log(increase());
console.log(increase());

즉시실행함수를 이용해서 클로저를 만들었다.

즉시실행함수는 호출된 직후 바로 소멸되지만 실행함수의 반환값이 increase 변수에 할당되 호출된다.

따라서 상위스코프의 자유변수인 num 을 참조하고 변경할수있게되고 , 외부에서는 num 을 조작할수없다.

이렇게 한가지조작만이아니라 여러가지 조작을할순없을까?

const counter = (function () {
  let num = 0;

  return {
    increase() {
      return ++num;
    },
    decrease() {
      return num > 0 ? --num : 0;
    },
  };
})();

console.log(counter.increase());
console.log(counter.decrease());
console.log(counter.decrease());
console.log(counter.decrease());
console.log(counter.decrease());

간단히 return 값에 함수객체형태로 하면된다.

캡슐화 와 정보 은닉

캡슐화는 객체의 상태를 나타내는 프로퍼티프로퍼티를 참조하고 조작할수있는 동작인 메서드

이 두가지를 하나로 묶는것을 말한다.

캡슐화는 객체의 특정 프로퍼티, 메서드를 감출목적으로 사용하기도한다. 이를 정보 은닉이라한다.

대부분의 객체지향 언어는 접근제한자를 통해서 이를 처리할수있는데 자바스크립트는 제공하지않는다.

기본적으로 모두 외부에 공개되있고 그렇기에 public 으로 설정되있다.

ES2022 에서 private 변수선언이 표준이됬다.

#을 붙여서 변수선언 하게되면 private 선언이된다.

반응형

'프론트엔드 > JavaScript' 카테고리의 다른 글

[23일] array method  (1) 2022.12.01
[22일] this  (0) 2022.12.01
[21일] JS 실행컨텍스트  (1) 2022.11.29
[16일차] SPA  (2) 2022.11.21
[Deepdive] 22장 this  (0) 2022.04.13