함수와 함수가 선언된 렉시컬 환경과의 조합?
(이는 조금 적응해야지 이해할 수 있다..)
외부 함수의 실행 컨텍스트가 사라진 이후에도
내부 함수가 여전히 외부 함수의 변수에 접근할 수 있는 상태를 설명하는 개념
외부 함수의 변수를 참조하는 내부 함수
클로저는 그래서 실제 확인하고 이론을 봐야 조금 더 이해할 수 있다.
식별자를 부를 때는
앞의 선언 function const
빼고 부르면 된다.
console.log(a)
var a = 10
의 값은 undefined
가 나온다
선언과 할당은 별개로 진행되기 때문에
평가 단계와 실행 단계를 나눠서 생각하는게 좋다
그래서 var
를 쓰면 머리아파지게 됨.
그러나 const
를 쓰면 에러가 찍히는 이유가
이미 참조할 식별자 조차 없기 때문에 에러가 난다.
let
과 const
는 호이스팅이 되고 의도적으로 레퍼런스 에러를 반환한다.
호이스팅은 선언된 식별자를 레코드 안에 기재하는 것 자체를 호이스팅이라 한다.
초기 값이 할당이 안되니까 에러가 난다고 생각하면 된다.
즉 참조할 값이 없기 때문에 에러를 내보내는 것이지
값이 있어야 참조를 할 수 있다.
console.log(a)
const a = 10;
의 경우
a
는 참조할 값이 아예 없기 때문에 에러가 나는데
consta = 10
할당문이 올때 까지 기다리는데
일시적으로 변수를 참조할 수 없을 때 사각지대 TDZ라고 함
a
는 레코드로 호이스팅 되었는데 참조할 수 없는 상태이기 때문에
이런게 있다 정도로 이해하고 있기
전역 실행컨텍스트의 아우터는 null
이다.
const closureFunc = outerFn();
은
레코드에 값이 할당이 될까 안될까? 할당 안됨
왜냐면 값이 레코드에 없기 때문이다.
outerFn
의 레코드와 아우터중에
아우터는 이제 Global
을 바라보게 된다.
이제 함수는 return문
을 만나면 함수는 바로 끝난다
즉 return
밑의 값은 무조건 무시가 된다.
근데 이런식으로 JS
에서는 함수는 return
을 보자마자
바로 콜 스택 바깥으로 빠져나갔음에도? 그래도 메모리가 남아있다.
즉 이 메모리가 어디에 간다? => Heap
이라는 공간에 메모리가 남아있다.
그래서 콜 스텍 바깥으로 빠져나갔으면 끝나야 하지만
Heap
이라는 공간에 갇혀있어서 클로저 === 폐쇄
라는 의미가 되는 것 같다.
글로벌 컨텍스트의 아우터는 null
이제 메게변수의 값이 들어가 있다면 그 값도 레코드에 포함된다.
메게 변수도 undefined
도 안들어간다.
call stack의 call
은 함수가 실행 되었을 때 쌓이기 때문에 이름이 붙었다.
전역 실행 컨텍스트도 함수로 생각해도 무방하다.
전역에 해당하는 것도 함수로 생각해야 햇갈리지 않는다
엄밀히 말하면 전역 실행컨텍스트와 함수 실행컨텍스트는 다르지만
같은 취급을 해야 햇갈리지 않는다는 것이다.
내부 함수가 외부함수를 참조하고 있을 때
이 조건이 없으면 클로저라는 메모리를 사용할 이유가 없다.
이런 조건이 없으면 클로저는 생성되지 않는다.
예를 들어서 movie.js
에서 function
안에 foreach
와 addEventlistener
가 있을 때
실행 컨텍스트가 어떻게 쌓이는지 이걸 순서를 정리하면
먼저 저 둘을 담고있는 함수가 실행 컨텍스트에 쌓이고
그 다음에 forEach
는 메게변수를 담는데 그 메게변수도 쌓이고
이제 forEach
는 즉시실행함수라 사실 계산도 안하고 핑 하고 사라진다
즉 컨텍스트에 왔다 바로 사라지는 console
같은 느낌이다.
그런 다음 addEventListener
은 실행 컨텍스트에 쌓이나?
아니다 쌓이지 않는다
이 친구는 Web api
에서 관리하기 때문에
따로 task queue
통로를 타고 따로 관리가 된다.
그 이벤트 루프라는 call stack
이 따로 존재한다.
JS
는 싱글 쓰레드라서 한번에 한가지 일밖에 하지 못함
async await
을 쓰지 않으면
web api
요청할 때 코드가 밑으로 내려가는데
JS
는 그냥 손이 하나이기 때문에 한번에 한가지 일밖에 못한다
그러나 api
요청 setTimeout
이런것들을 Web api
로 넘겨준다
Call stack
이 그냥 손가락 하나 Web api
는 싱글 쓰레드가 아님
setTimeout
을 1,2,3 있다고 치면 모두 다 동시에 새는 것이다.