[JavaScript] 클로저

zmin·2022년 4월 25일
0
post-thumbnail

모던 자바스크립트 Deep Dive, 이웅모
코어 자바스크립트, 정재남

정리에 앞서...

그냥 지금 내가 헷갈리는 것들을 정리를 좀 하면...

  • 스코프는... 식별자의 유효범휘이며 함수의 정의가 평가될 때 생성
  • 실행 컨텍스트는... 소스코드가 실행될 때 선언된 식별자 등 실행하는데 필요한 정보를 관리하고 제공하는 역할을 하며 코드가 실행될 때 새로 생성 후 스택에 삽입
  • this는... 자신이 속한 객체/인스턴스를 칭하는 변수이기 때문에 호출하면서 결정/지정

상위 스코프

함수 정의가 평가되어 함수 객체를 생성할 때 해당 함수의 스코프를 결정하는 것뿐만 아니라
현재 실행되고 있는 실행 컨텍스트의 렉시컬 환경도 새로 생성되는 함수 객체의 [[Environment]] 슬롯에 저장

이후 이 함수를 호출할 때 만들어지는 실행 컨텍스트에서 외부 렉시컬 환경에 대한 참조(outerEnvironmentReference) 값을 설정할 때 이 함수 객체의 [[Environment]] 슬롯의 값을 가져와서 저장

즉, [[Environment]] 슬롯에 저장되는 값이 곧 상위 스코프이며 이는 결국 해당 함수를 정의했던 스코프, 렉시컬 환경을 말함

클로저(closure)

자바스크립트는 garbage colletion을 이용하여 참조되지 않는 메모리들을 자동으로 해제할 수 있도록 메모리 관리 시스템이 짜여있음
이걸 역으로 만약 여전히 참조되고 있다면 garbage colletion의 대상이 되지 않는다는 것을 이용하는 것이 클로저


보통 실행 컨텍스트가 종료되면 해당 렉시컬 환경도 같이 소멸됨
하지만 위에서 말한 것과 같이 만약 렉시컬 환경도 누군가 참조하고 있다면 소멸X

아래와 같이 중첩된 함수가 있을 때 내부함수(inner)를 외부로 반환하여 사용하는 경우 외부함수(outer)가 종료된 이후에도 반환된 내부함수 객체의 [[Environment]] 슬롯이 외부함수의 렉시컬 환경을 참조하기 때문에 소멸X

function outer(){
  	function inner(){
  		console.log('inner');
  	}  
  	return inner;
}

const func = outer();
func(); // inner

하지만 보통 위와 같이 상위 스코프의 어떤 식별자도 참조하지 않는 경우를 클로저라고 하진 않음
또한 모던 브라우저들이 이 경우 최적화를 위해 상위 스코프를 기억하지 않음

function outer(){
  	let a = 1;
  	function inner(){
  		console.log(++a);
  	}  
  	return inner;
}

const func = outer();
func(); // 2

위와 같이 상위 스코프의 식별자(a)를 참고하는 경우, 보통 외부 함수보다 내부 함수가 더 오래 살아남는 경우를 클로저라고 부르게 됨
outer의 생명주기는 끝났지만 outer내부의 식별자 afunc(inner)에 의해서 계속 참조되고 있기 때문에 소멸되지 않음

꼭 함수를 반환해야 하는 것은 아니며 일반 객체와 같이 참조형 데이터의 형태로 반환한다면 클로저를 사용할 수 있음

정보 은닉 with 클로저

const counter = (function outer(){
  	let count = 1;
  	function inner(){
  		return ++count;
  	}  
  	return inner;
}());	// 즉시 실행 함수


console.log(counter());	// 2
console.log(counter());	// 3

함수의 반환 값으로 public으로 지정하고 싶은 변수나 함수 등 정보를 모아서 객체로 지정하게 되면
외부에서는 그 값들만 새로운 변수에 할당받아 사용할 수 있게되며
내부 값들은 이미 실행이 종료된 상태이기 때문에 (그러나 public으로 return한 값들이 참조하고 있어서 garbage collection의 대상이 되진 않음) 따로 접근할 수 있는 방법이 없게 됨 -> private

이 방법으로 public, private를 흉내낼 수는 있지만 완벽하게 구현하기에는 어려움이 있음

profile
308 Permanent Redirect

0개의 댓글