[TIL]JavaScript_클로저

Sohee Yeo·2023년 6월 14일
0
post-thumbnail

클로저(Closure)

클로저는 함수와 해당 함수가 선언된 렉시컬 환경의 조합이다. 외부 함수의 실행이 종료된 후에도 중첩 함수는 외부 함수의 변수를 기억하여 참조할 수 있다. 이러한 중첩 함수를 클로저라고 한다.

📌 렉시컬 스코프
함수가 정의된 위치에 의해 상위 스코프가 결정되는 스코프

함수 객체의 내부 슬롯 [[Environment]]

함수 객체를 생성할 때 자신이 정의된 위치에 의해 결정된 상위 스코프의 참조를 자신의 내부 슬롯 [[Environment]]에 저장한다.

const x = 1;

function funcOne() {
	const x = 5;
  
// 함수의 호출 위치와 상위 스코프는 아무런 관계가 없다.
	funcTwo();
};

function funcTwo() {
  // 함수 funcTwo는 자신의 상위 스코프를 내부슬롯 [[Environment]]에 저장하여 기억한다.
 console.log(x);
};

funcOne(); // 1
funcTwo(); // 1

클로저와 렉시컬 환경

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

const x = 1;

function outer() {
	const x = 5;
  
  	// 중첩 함수 inner은 클로저
  	const inner = function() {
      console.log(x);
    };
	return inner;
};

// 함수 outer을 호출하면 중첩 함수 inner을 반환하고, outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거된다.
const innerFunc = outer();
innerFunc(); // 5

위의 예제에서, 함수 outer의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거되지만, outer의 렉시컬 환경까지 소멸하는 것은 아니다. 함수 outer의 렉시컬 환경은 함수 inner의 [[Environment]] 내부 슬롯에 의해 참조되고 있고 inner은 전역 변수 innerFunc에 의해 참조되고 있다.
📢 클로저에 의해 참조되는 상위 스코프의 변수(예제에서 outer 함수의 x)를 자유 변수라고 부른다. 클로저란 자유 변수에 묶여있는 함수라고도 할 수 있다.

클로저의 활용

상태(state)를 안전하게 은닉, 특정 함수에게만 상태 변경 허용
함수가 호출될 때마다 횟수를 누적하여 출력하는 카운터를 만들어보자.

let num = 0;

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

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

카운트 상태(num)는 increase 함수가 호출되기 전까지 변경되지 않아야 하고, 카운트 상태(num)는 increase 함수만이 변경할 수 있어야 한다. 하지만 위의 예제에서 카운트 상태가 전역에서 관리되고 있으므로 누구나 접근할 수 있고 변경할 수 있는 위험이 있다.

// 카운트 상태 변경 함수
const increase = (function() {
  	let num = 0;
  	// 클로저
	return function() {
    	return num++
    };
}());

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

위의 예제에서, 즉시 실행 함수가 반환한 클로저는 카운트 상태를 유지하기 위한 자유 변수 num을 어디서 호출하든지 참조하고 변경할 수 있다. 또한 num 변수는 은닉된 private 변수이므로 의도되지 않은 변경을 걱정하지 않아도 된다.

정리

  • 클로저는 외부 함수의 실행이 종료된 후에도 외부 함수의 변수를 기억하여 참조할 수 있는 함수이다.
  • 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다.
  • 클로저는 상태(state)를 은닉하고 특정 함수에게만 상태 변경을 허용하여 상태를 안전하게 변경하고 유지하기 위해 사용한다.



참고

모던 자바스크립트 Deep Dive (도서)

profile
실패에 무딘 사람. 프론트엔드 개발자를 꿈꿉니다

0개의 댓글