클로저

joseph·2023년 5월 14일
0

개념정리

목록 보기
5/16

https://www.youtube.com/watch?v=PJjPVfQO61o&list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&index=84

💡 어떤 함수 내부에서 선언된 변수 a를 참조하는 내부 함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 끝난 후에도 변수 a가 사라지지 않는 현상

Recap

실행 컨텍스트 : 코드를 실행하는데 필요한 환경을 제공하는 객체

  • 렉시컬 환경
    • Record - 식별자와 식별자에 바인딩 된 값을 기록
    • Outer - 외부 렉시컬 환경을 참조할 수 있도록 한다

클로저 예제

function outFn(x){
	return function(){
		return x + y;
	}
}

const add = outFn(2)
console.log(add(7))

위의 코드가 실행되는 과정은 아래와 같다

  1. 전역 코드 평가가 이루어진다
    1. 위 코드에서 Global 렉시컬 환경의 Record에 들어갈 변수는 outFn, add 두가지
    2. 전역 평가가 이루어지는 중이어서 outer는 null
  2. 평가가 끝나면 순차적으로 코드 실행
    1. const로 선언된 add 변수에 값을 할당하기 위해 outFn함수가 실행
      • 똑같이 outFn함수의 렉시컬 환경 생성, 평가 진행
    2. outFn함수 평가를 하면서 파라미터 x와 익명 함수를 호이스팅해서 record에 기록
    3. outer는 상위 스코프인 global 렉시컬 환경을 가리킨다
    4. record에 선언된 파라미터 x에는 const add = outFn(2) 라고 되어있으니 2라는 값을 할당

**outFn함수의 outer가 global렉시컬 환경을 가리키는 이유

  • global 렉시컬 환경이 만들어지면서 outFn함수의 변수가 입력되었기 때문.
  • 즉, 어떤 환경에서 변수가 선언되었는지가 중요하다!**
  1. 이후 outFn함수에 실행할 코드가 없으니 callstack에서 outFn 렉시컬 환경은 pop되고
    다시 global 렉시컬 환경으로 들어와서 outFn함수의 return값인 익명 함수를 add변수에 할당하고 record에 있는 add 변수에 익명 함수를 할당한다.(const add = function())
  2. 마지막 코드인 console.log 함수를 실행
    1. 위에서 add 변수는 익명 함수이므로 다시 add의 렉시컬 환경 생성
      const add = function(y){ return x+ y }
    2. 변수 y를 호이스팅해서 record에 기록하고 outer는 상위 렉시컬 환경인 sum을 가리킨다

근데 아까 실행이 끝나고 pop 해버렸기 때문에 지금 콜스택에는 outFn 렉시컬 환경이 없다.
그런데도 outer가 outFn 렉시컬 환경을 가리킬 수 있는 이유는
위에서 설명했듯 익명 함수가 선언되는 시점이 outFn 함수 내부 평가 과정에서 익명 함수가 선언되기 때문에 outer가 outFn을 가리킬 수 있는 것

c. 렉시컬 환경을 생성했으니 callstack에 push

d. console.log(add(7))이니 y변수에 7을 기록

  1. 다음 코드인 return x + y를 실행
    1. outer를 통해 x변수에 할당된 값을 찾아 x + y 실행
  2. return 값 9가 나온다

콜스택에 렉시컬환경이 존재하지 않아도 outer를 통해 참조할 수 있는 현상을 클로저라 한다

profile
내일도 모레도 글피도 엉금엉금

0개의 댓글