자바스크립트 엔진은 Memory Heap과 Call stack으로 구성되어 있음 (ex. 크롬 V8 Engine)
자바스크립트는 싱글 스레드, 이 의미는 Call stack (호출 스택)이 한 개 라는 것
-- Memory Heap : 메모리 할당이 일어나는 곳 (우리가 선언한 변수, 함수 등이 담겨 있음)
-- Call Stack : 코드가 실행될 때 쌓이는 곳
단일 콜 스택을 갖는다는 의미는 동기적으로 처리된다는 것을 의미
비동기 요청을 처리하기 위해서는 자바스크립트를 실행하는 환경인 브라우저나 Node.js가 담당
자바스크립트는 싱글 스레드 기반 언어기 때문에 한번에 하나의 함수만 처리하지만 이벤트 루프를 기반한 동시성 모델을 지원
이벤트 루프는 콜 스택과 콜백 큐의 상태를 체크하며 콜 스택이 빈 상태가 되면 콜백 큐의 첫번째 함수를 콜 스택에 넣음 이러한 행위의 반복이므로 루프라고 부르는 것이고 반복적인 행동은 틱(TicK)이라고 함
콜백 큐에는 Task Queue와 Micro Queue가 있음
-- Task Queue (태스크 큐, 매크로 큐)에는 Web API가 콜백함수를 콜백 큐에 넣은 setTimeout(), setInterval()과 UI렌더링, RequestAnimationFrame()이 담김
-- Micro Queue (마이크로 큐)에는 비동기 호출을 넘겨 받아 태스크 큐보다 우선순위가 더 높은 Promise(then)과 mutationObserver, process.nextTick, async이 담김
-- 따라서 이벤트 루프의 비동기 작업 처리 우선순위는 마이크로 큐 -> 애니메이션 프레임 -> 태스크 큐 순
이벤트 루프는 우선적으로 마이크로 큐를 확인하고 그 안에 콜백 함수가 있다면 콜 스택으로 옮김 없다면 매크로 큐 (태스크 큐)를 확인 후 처리
웹 API는 JS 엔진이 아님
웹 API는 브라우저에서 제공하는 APi로 DOM, AJAX, TimeOut이 있음
콜 스택 (호출 스택)에서 실행된 비동기 함수는 웹 API를 호출하고 웹 API는 콜백함수를 콜백 큐 (매크로 큐 (=Task Queue), 마이크로 큐)에 넣음
실행 컨텍스트는 자바스크립트 코드 실행환경 (변수 객체 (arguments, variable), 스코프 체인, this)에 대한 정보를 담고있는 객체
실행 컨텍스트 구성요소
-- Lexical Environment
-- Variable Environment
-- this 바인딩
실행 컨텍스트는 전역 컨텍스트, 함수 컨텍스트 2가지 종류
처음 자바스크립트 코드를 실행하는 순간 전역(글로벌) 컨텍스트가 생성되고 실행 컨텍스트에 쌓임
전역 컨텍스트 생성 후 함수 컨텍스트는 함수를 호출할 때마다 실행 컨텍스트 스택에 쌓이고 호출이 끝나면 제거됨
컨텍스트 생성 후 함수에 필요한 변수들은 변수 객체 안에서 값을 찾고 없으면 스코프 체인을 따라 올라가며 찾음
함수 실행이 마무리 되면 해당 컨텍스트는 제거 (단, 클로저 제외) 모든 코드가 종료되면 전역 컨텍스트는 제거
클로저는 자신이 선언 됐을 때의 렉시컬 스코프를 기억하여, 스코프 밖에서 호출 되어도 선언 됐을 때에 렉시컬 스코프에 접근할 수 있는 함수
클로저는 자신이 선언될 때의 환경 (Lexical environment)을 기억하는 함수다라고 말할 수 있음
-- "렉시컬(Lexical)" 이라는 명칭이 붙은 이유는 자바스크립트 컴파일러가 소스코드를 토큰(Token)으로 쪼개서 의미를 부여하는 렉싱(Lexing) 단계에 해당 스코프가 확정되기 때문
몇몇 프로그래밍 언어에서는 클로저 구현이 불가능하거나 특수한 방식으로 함수를 작성해야 클로저를 만들 수 있지만, 자바스크립트에서는 모든 함수가 자연스럽게 클로저가 됨
자바스크립트의 함수는 숨김 프로퍼티인 [[Environment]]를 이용해 자신이 어디서 만들어졌는지를 기억, 함수 본문에서 [[Environment]]를 사용해 외부 변수에 접근
클로저를 사용하는 이유
-- 정보를 은닉하기 위해
-- 전역변수 사용을 억제하기 위해
-- 현재 상태를 기억하고 변경된 최신 상태를 유지 하기 위해 (useState)
커링은 함수에 n개의 인자를 받는 대신, n개의 클로저 함수를 만들어 각각 인자를 받게하는 방법
커링은 클로저와 별개인 무언가가 아니라 클로저의 특징을 이용한 기법, 클로저의 외부 함수 변수의 값을 고정할 수 있음에 유용
this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수
자바스크립트 일반 함수, 콜백함수의 this는 어디에 선언 되었든 전역 객체를 바인딩
-- 즉, 어디서 호출 했냐에 따라 결정됨
-- 브라우저에서는 window, node에서는 global 근데 요즘은 globalThis로 통합
-- 엄격 모드 (use strict)에서는 undefined를 반환
객체 메서드 내부의 this는 메서드를 소유한 객체, 즉 해당 메서드를 호출한 객체에 바인딩
화살표 함수의 this는 언제나 자신이 선언 됐을 때의 this, 이를 렉시컬 this라고 함
자바스크립트를 실행하기 위해서는 자바스크립트 엕빈이 필요하고 웹 브라우저는 자바스크립트 엔진을 내장하고 있음 브라우저마다 엔진의 종류는 다르지만 코드를 실행하는 방식은 비슷함
소스코드를 만나면 파싱하여 AST (Abstract Syntax Tree)로 변환
인터프리터는 AST를 기반으로 바이트코드를 생성
인터프리터가 바이트 코드를 실행시, 자주 사용되는 함수 및 타입 정보등이 있는 프로파일링 데이터와 같이 최적화 컴파일러에게 보냄
최적화 컴파일러는 프로파일링 데이터를 기반으로 최적화된 코드를 생성
하지만 프로파일링 데이터 중 잘못된 부분이 있다면 최적화 해제를 하고 다시 바이트 코드를 실행해서 이전 동작을 반복