Closure

DD·2021년 1월 18일
0

프로그래밍 이론

목록 보기
7/12
post-custom-banner

Closure

“A closure is the combination of a function and the lexical environment within which that function was declared.”
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다.

렉시컬 환경이란 무엇일까?

  1. 정의

    • 변수나 함수 등의 식별자를 정의할 때 사용되는 명세

    • 중첩된 어휘적 환경에 기반해 동작

    • Environment Record와 outer속성 포함

  2. 관련 문법

    • 함수 선언

    • 블럭문

    • Try-Catch문의 Catch절

  3. 종류

    • 전역 환경

    • 모듈 환경

    • 함수 환경

const str = "어디서 실행될까??"
console.log("str");

function hello() {
	const greeting = "안녕하세요";
    console.log(greeting)
}
hello()

이 코드가 실행되면 큐 스택에는 Global EC(Execution Context, 실행 컨텍스트), hello() EX 순으로 쌓이게 된다.

EC 안에는 몇 가지 상태 컴퍼넌트가 존재하는데,
대표적으로 아래 세 가지가 있다.

  • function
    function은 현재 컨텍스트가 함수로 생성되었다면 그 함수 객체를 가르킨다.
    (Global EC의 경우 이 값은 null이 된다)

  • Variable Environment(VE)
    VE는 두가지 속성을 가진다

    • Environment Record :
      현재 실행 컨텍스트 내에서 호이스팅 되는 식별자에 대한 기록(var, 함수선언문 등)
      outer : 바깥에 있는 ER을 참조한다. Global에서는 null된다
  • Lexical Environment(LE)
    LE는 VE와 비슷하지만 조금 다르다

    • Environment Record :
      VE의 ER뿐만 아니라 let, const로 선언된 변수, 함수 표현식도 포함한다.
    • outer : 바깥에 있는 ER을 참조한다. Global에서는 null된다

함수는 실행 컨텍스트를 생성할 수 있는 객체로, Environment 속성이 있다.

이 속성에는 '자신이 선언 될 때의 Environment Record가 들어있다.

즉, 위 예시에서 hello 함수의 Environment는 global EC의 LE와 같다.

그래서 Closure가 무엇일까?

처음 만들어 질 때의 어휘적 범위를 그대로 유지한 함수.
어휘적 범위(LE) 바깥에서 해당 범위에 접근할 수 있다.

스코프는 함수를 호출할 때가 아니라 함수를 어디에 선언하였는지에 따라 결정된다.
이를 렉시컬 스코핑(Lexical scoping)라 한다.
위 예제의 함수 innerFunc는 함수 outerFunc의 내부에서 선언되었기 때문에 함수 innerFunc의 상위 스코프는 함수 outerFunc이다.
함수 innerFunc가 전역에 선언되었다면 함수 innerFunc의 상위 스코프는 전역 스코프가 된다.

1  function hello() {
2 	const greeting = '안녕하슈';
3     
4     return function() {
5     	console.log(greeting);
6     };
7 }
8 
9 const say = hello();
10 say();

코드가 실행되면 Global EC의 LE에 hello, say가 저장된다.

line 9에서 hello가 실행되면 hello EC(실행 컨텍스트)가 생성되고
LE에 greeting이 저장된 후 익명함수를 return한다. 그리고 보통은 함수 종료와 함께 hello EC는 사라진다. (다만 이 경우에는 사라지지 않는다.)

return된 익명함수는 say에 할당되고

line 10에서 say가 실행되어 line 4~6에 선언된 함수, 그 내부의 console.log가 greeting이라는 변수를 찾는다.

이 때, Global EC에 say라는 식별자가 hello 안에 있는 greeting을 참조하고 있기 때문에, hello 함수는 종료되어도 메모리에서 hello가 사라지지 않고 있는 것이다

함수는 자기자신이 선언될 때의 LE를 Environment라는 속성에 저장하고, EC를 만들면서 그 값을 outer에 넣는다.
이 과정이 있기 때문에 자신이 선언되었을 때 속해있었던 실행 컨텍스트의 값을 참조할 수 있는 것이다 => closure!!

왜 Closure를 사용해야하나?

  1. 캡슐화

  2. 컨텍스트 공유 (함수가 종료되어도 지역변수 사용)

  3. 함수를 반환함으로써 재사용 가능

profile
기억보단 기록을 / TIL 전용 => https://velog.io/@jjuny546
post-custom-banner

0개의 댓글