# 들어가며

클로저에 관한 내용입니다. 개념 위주로 작성하였습니다. 



## Closure

책과 여러 자료를 보고 정리 해봤을 때, 클로저는 아래와 같은 개념을 말한다고 나름의 정리를 해봤다.

> 클로저는 함수 자신과 함수 자신이 선언된 어휘적 환경을 기억하고 있다. 
>
> 따라서 생명주기가 끝난 외부 함수의 변수를 **스코프 체인** 을 통해서 **참조** 를 할 수 있다.



코드를 보자.

```javascript
function outerFunc() { // 외부 함수
  var x = 10;
  function innerFunc() {
    console.log(x);
  }
  return innerFunc;
}

var inner = outerFunc();
inner(); // 10
```



`ffInner = fOuter()` 를 했을 때, `fOuter()의 execution context` 는 call stack에서 사라졌다. 왜냐하면 자신이 할 일을 다 했기 때문이다.

그렇다면 **`ffInner()` 는 어떻게 `vOuter` 를 출력할 수 있을까?** `vOuter` 는 `fOuter` 안에 있는데?



먼저 이런 상황, `fOuter` 가 자신의 일을 다 해서 call stack에서 사라진 경우를 `fOuter의 생명주기가 끝났다` 라고 한다. 따라서 존재하지 않기 때문에, 일반적으로는 **값을 참조할 수 없다**. 그럼 **어떻게 참조를 한걸까?**



답은 변수 객체와 스코프 체인이다.



## 변수 객체, 스코프 체인

![closure](https://poiemaweb.com/img/closure.png)

> -[참고3](https://poiemaweb.com/js-closure)



실행 컨텍스트와 활성 객체에 대한 설명은 [이 자료](https://velog.io/@04_miffy/this-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8) 에 있다.



이때  `funcOuter()` 가 자신의 일을 다 했어도, `funcInner()` 가 자신의 스코프안에 있는 `x` 를 참조하기 때문에, `funcOuter() 의 실행컨텍스트` 는 사라져도 `funcOuter()의 변수 객체(활성 객체)` 는 살려둔다.



따라서, `inner();` 를 실행했을 때 `funcOuter()의 변수 객체` 에 접근함으로써 `funcOuter()` 내의 `identifier` 들을 참조할 수 있는 것이다. 그리고 이 때 참조는 **스코프 체인** 을 통해 이루어진다.



스코프 체인은 스코프가 연결되어있다는 말인데, 그렇다면 **어떻게 연결되어있을까**?



![내부구조](https://s3.ap-northeast-2.amazonaws.com/tyle.io.seoul/tyle.post/gU/gUL6NX3jTI1480309443_cont.png)

> 함수가 생성되면 *Execution Context* 가 생성되고, 그리하여 *Lexical Environment* 내 *outer Lexical Environment* 가 상위 *Environment Record* 와 연결되면서 내부 함수 정보를 탐색할 수 있게 됩니다.
>
> -[참고4](https://knphouse.co.kr/91?category=693064)

즉 Execution context가 만들어질 때, (그 안에서) 외부로 접근할 수 있는 `outer` 와 식별자들의 바인딩을 기록하는 객체인 `Environment Record` 가 만들어진다. 따라서 `outer` 를 통해서 상위 `Environment Record` 에 접근하여 임의의 식별자에 접근할 수 있는 것이다.



## 참고자료

1. You Dont' Know JS (1)

2. 인사이드 자바스크립트

3. https://poiemaweb.com/js-closure

4. https://knphouse.co.kr/91?category=693064