JavaScript Under The Hood: 이벤트 루프

Dec 01 2022
처음부터 기능을 탐색하여 JavaScript를 마스터해 봅시다. 정의되지 않은 오류에 직면했거나 변수의 범위를 식별하는 데 어려움을 겪은 적이 있습니까? 코드가 어떻게 작동하는지 알지 못한 채 오류를 디버깅하는 것은 정말 시간이 많이 걸립니다. 이 블로그에서는 실행 컨텍스트, 호출 스택 및 콜백 큐와 관련된 이벤트 루프와 같은 고급 개념이 실제로 어떻게 작동하는지 보여줍니다.

JavaScript의 기능을 처음부터 탐색하여 JavaScript를 마스터합시다

Unsplash에 있는 Marc St의 사진

정의되지 않은 오류에 직면했거나 변수의 범위를 식별하는 데 어려움을 겪은 적이 있습니까?

코드가 어떻게 작동하는지 알지 못한 채 오류를 디버깅하는 것은 정말 시간이 많이 걸립니다.

이 블로그 에서는 , 및 event loop관련하여 고급 개념이 실제로 어떻게 작동하는지 보여드리겠습니다 .execution contextcall stackcallback queue

면책 조항 — 개념은 믿을 수 없을 정도로 지식 집약적이고 상호 연결되어 있으므로 눈을 깜빡이지 마십시오!

자바스크립트 엔진

Google의 V8 엔진은 JavaScript 엔진의 잘 알려진 그림입니다. 예를 들어 Chrome과 Node.js는 모두 V8 엔진을 사용합니다. 기본적으로 V8 엔진은 두 부분으로 구성됩니다.

  1. Call Stack : 모든 코드가 내부에서 실행됩니다. 스택 데이터 구조처럼 작동합니다. 즉, LIFO(Last In First Out) 개념을 따릅니다.
  2. 메모리 힙: 메모리 할당이 발생하는 곳입니다. 힙 데이터 구조와 달리 메모리일 뿐입니다.

글로벌 실행 컨텍스트 또는 GEC는 스크립트 파일을 수신할 때마다 JavaScript 엔진이 생성하는 기본 실행 컨텍스트입니다.

함수 내부에 있지 않은 모든 JavaScript 코드는 GEC. 다음 단계는 GEC— 에서 수행됩니다.

  • 모든 변수와 함수를 글로벌 규모로 저장하기 위한 메모리 공간 구축
  • 전역 개체를 생성합니다.
  • 키워드 생성this

코드가 실행되는 위치에 따라 위치가 결정됩니다 this. 예를 들어 Node.js에서는 고유한 전역 객체를 가리키지만 브라우저에서는 window객체를 가리킵니다.

브라우저 콘솔

호출 스택(또는 함수 실행 스택)

자바스크립트는 single-threaded이미 들어보셨듯이 입니다. 그러나 실제로 무엇을 의미합니까?

call stack이는 JavaScript 엔진에 또는 가 하나만 포함되어 있음을 의미합니다 function execution stack.

  • 아시다시피 컴파일러가 처음으로 코드를 탐색할 때마다 JS 엔진은 컴파일러에 의해 Global Execution Contextor 를 생성하고 .GECCall Stack
  • 전체 코드는 에서 하나씩 실행되며 Global Execution Context함수 정의 또는 변수 선언을 위한 메모리를 할당하고 거기에 저장합니다.
  • 그러나 함수 호출이 발견되면 함수의 코드를 실행하기 위해 Functional Execution Contextor 를 생성한 다음 의 맨 위에 추가합니다 .FECcall stack
  • call stack인터프리터는 함수가 종료될 때마다 함수를 제거합니다 . 함수는 범위 또는 return 문 끝에 도달할 때 종료됩니다.
  • 마지막으로 전체 코드를 실행 GEC하면 Call Stack.

걱정하지 마세요. 예를 들어 설명하겠습니다.

function f1{
  console.log('f1');
}

f1();
console.log('end');

2단계: — 이 예에서는 첫 번째 라인이 실행됩니다 f1. 정의 를 위해 메모리가 할당 f1되고 저장됩니다.

3단계: — 두 번째 줄에서 함수가 호출됩니다. 이 함수 호출의 경우 Function Execution Context or FEC가 생성되고 Call Stack.

4단계: — 이제 전체 f1()가 한 줄씩 실행되고 실행이 끝나면 에서 제거됩니다 Call Stack.

5단계: — 그러면 마지막 줄 console.log('end')이 실행되고 콘솔에 'end'가 인쇄됩니다. 마지막으로 전체 코드를 실행 Global Execution Context하면 Call Stack.

JS는 비동기 작업을 어떻게 관리합니까?

우리 모두가 알고 있듯이 JavaScript는 동기식 단일 스레드 언어(한 번 에 하나의 작업)이며 call stack내부에 들어오는 모든 것을 즉시 실행하는 단일 스레드입니다.

하지만 5초 후에 무언가를 실행해야 한다면 어떻게 해야 할까요? 우리는 안에 그것을 입을 수 있습니까 call stack?

아니요, 할 수 없습니다. call stack타이머가 없기 때문입니다 . 하지만 어떻게 할 수 있습니까?

이것은 JavaScript 런타임 이 들어오는 곳입니다.

자바스크립트 런타임 환경

DOM 이벤트 가 모두 JavaScript 엔진 에 대한 액세스 권한을 부여하여 GEC(Global Execution Context) 의 모든 속성을 사용할 수 있는 웹 APIsetTimeout() 의 일부 임에도 불구하고 JavaScript의 일부가 아니라고 console.log()지금 말씀드리면 마음이 아플 수 있습니다. 전역 객체 . 이러한 웹 API비동기 라고 합니다 .window

콜백 대기열이란 무엇입니까?

"콜백 큐" 또는 "태스크 큐"라고 하는 태스크 큐는 콜 스택의 현재 임무가 완료된 후에 실행되는 큐입니다. 웹 API에 등록된 작업은 웹 API에서 콜백 큐로 이동합니다.

콜백 대기열은 작업이 대기열에 추가된 순서대로 처리되는 호출 스택과 달리 작업이 FIFO 순서(선입선출)로 처리됨을 의미하는 대기열 데이터 구조처럼 작동합니다.

콜백 대기열

이벤트 루프란?

JavaScript 이벤트 루프는 호출 스택이 비는 즉시 콜백 대기열의 작업을 FIFO 순서로 호출 스택에 추가합니다.

호출 스택이 현재 일부 코드를 실행 중인 경우 이벤트 루프가 차단되고 스택이 다시 한 번 비워질 때까지 대기열에서 추가 호출을 추가하지 않습니다. 이는 JavaScript 코드가 완료까지 실행되는 방식으로 실행되기 때문입니다.

예를 들어 위의 개념을 이해해 봅시다.

  • 처음에는 Global Execution Context내부의 코드용으로 생성되어 call stack코드 GEC를 한 줄씩 실행합니다.
  • GEC첫 번째 라인을 실행하고 콘솔에 'Start'를 출력합니다.
  • 두 번째 줄을 실행하면 setTimeout()웹 API가 호출되고 setTimeout()타이머 기능에 대한 액세스 권한이 부여됩니다. 5000ms그런 다음 지연 시간으로 설정할 수 있습니다 .
  • callBack()를 통해 함수를 전달하면 웹 웹 API를 통해 콜백으로 등록됩니다 setTimeout().callBack()
  • 그런 다음 GEC첫 번째 줄을 실행하고 콘솔에 'End'를 인쇄합니다.
  • 모든 코드가 실행되면 GEC에서 제거됩니다 call stack.
  • 이후 5000 millisecondcallBack()등록된 함수를 web API, 로 이동합니다 call Back Queue.
  • Event loop기능 callBack()call Stack완료되면 모든 작업이 완료됩니다. 그리고 마지막으로 callBack()함수가 실행되고 콘솔에 'Call Back'이 출력됩니다.

function f1() {
    console.log('f1');
}

function f2() {
    console.log('f2');
}

function main() {
    console.log('main');
    
    setTimeout(f1, 0);
    
    f2();
}

main();

"f1"이 "f2"보다 먼저 인쇄될 것이라고 생각했다면 잘못된 것입니다. 그것은-

main
f2
f1

JavaScript의 논의된 메커니즘은 모든 콜백 함수 또는 API 요청에 적합합니다.

런타임 환경 내에서 두 번째 예제가 어떻게 작동하는지 단계별로 살펴보겠습니다.

  1. 처음에는 GEC내부에 생성 call stack되고 코드는 한 줄씩 실행됩니다 GEC. 메모리 힙 에 모든 함수 정의를 저장합니다 .
  2. the main()가 호출되면 a Function Execution Context (FEC)가 생성된 다음 호출 스택 내부로 들어갑니다. 그 후 main()함수의 모든 코드가 한 줄씩 실행됩니다.
  3. main이라는 단어를 인쇄하는 콘솔 로그가 있습니다. 따라서 console.log('main')실행되고 스택에서 나갑니다.
  4. setTimeout()브라우저 API가 발생합니다 . 콜백 함수는 이를 콜백 대기열에 넣습니다. 그러나 스택에서는 평소와 같이 실행이 발생하므로 f2()스택에 들어갑니다. 의 콘솔 로그가 f2()실행됩니다. 둘 다 스택에서 나갑니다.
  5. 그런 다음 main()스택에서 튀어나옵니다.
  6. 이벤트 루프는 콜 스택이 비어 있고 큐에 콜백 함수가 있음을 인식합니다. 따라서 콜백 함수 f1()event loop. 실행이 시작됩니다. 콘솔 로그가 실행되고 f1()스택에서 튀어나옵니다. 그리고 마지막으로 더 이상 실행할 스택과 큐에는 아무 것도 없습니다.

내 연습과 메모입니다. 도움이 되셨다면 아래의 박수 아이콘을 눌러 응원해주세요. 당신은 매체 에서 나를 따라갈 수 있습니다 .