[JS] 클로저

Jay ·2022년 8월 29일
0

클로저

함수와 그 함수가 선언된 렉시컬 환경과의 조합

function makeCounter(predicate) {
  // 카운트 상태를 유지하기 위한 자유 변수
  var counter = 0;
  // 클로저를 반환
  return function () {
    counter = predicate(counter);
    return counter;
  };
}

// 보조 함수
function increase(n) {
  return ++n;
}

// 보조 함수
function decrease(n) {
  return --n;
}

// 함수로 함수를 생성한다.
// makeCounter 함수는 보조 함수를 인자로 전달받아 함수를 반환한다
const increaser = makeCounter(increase);
console.log(increaser()); // 1
console.log(increaser()); // 2

// increaser 함수와는 별개의 독립된 렉시컬 환경을 갖기 때문에 카운터 상태가 연동하지 않는다.
const decreaser = makeCounter(decrease);
console.log(decreaser()); // -1
console.log(decreaser()); // -2

렉시컬 스코핑

함수를 어디에서 정의했는지에 따라 상위 스코프를 결정한다. 이를 렉시컬 스코프(정적 스코프)라 한다.

==

detail : 렉시컬 환경의 "외부 렉시컬 환경에 대한 참조"에 저잘할 참조값, 즉 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경에 의해 결정된다. 이것이 렉시컬 스코프이다.

[[Environment]]

함수는 자신의 내부 슬롯 [[Environment]]에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장한다.

클로저와 렉시컬 환경

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

외부함수의 실행 컨텍스트가 종료되더라도 out 함수의 렉시컬 환경은 inner 함수의 [[environment]]내부 슬롯에 의해 참조되고 있고, inner 함수가 전역 변수에 의해 참조되고 있다면 가비지 컬렉션의 대상이 되지 않는다.

클로저는 중첩 함수가 상위 스코프의 식별자를 참조하고 있고 중첩 함수가 외부 함수보다 더 오래 유지되는 경우에 한정하는 것이 일반적.

클로저에 의해 참조되는 상위 스코프의 변수를 자유 변수(free variable)이라 부른다.
(closure -> 자유 변수에 대해 닫혀있음을 뜻함)

클로저의 활용

상태를 안전하게 변경하고 유지하기 위해 사용한다.
즉, 상태를 안전하게 은닉(information hiding)하고 특정 함수에게만 상태 변경을 허용하기 위해 사용.

const increase = (function () {
	let num = 0;
  
  return function () {
  return ++num;
  }
}())

캡슐화와 정보 은닉

Javascript는 public, private, protected 같은 접근 제한자를 제공하지 않기 때문에, 완벽한 정보 은닉을 지원하지 않는다.

2021년 기준 클래스에 private 필드를 정의할 수 있는 표준 사양이 제안되어 있다.

profile
Jay입니다.

0개의 댓글