JS 엔진:
- JS 코드를 실행하는 프로그램입니다. 전. 구글의 V8.
- V8은 Chrome, Node.js를 지원합니다
- 다른 브라우저에는 자체 JS 엔진이 있습니다.
JS 엔진은 두 부분으로 구성됩니다.
- 콜 스택: 실행 컨텍스트를 사용하여 코드가 실행되는 위치
- 힙: 구조화되지 않은 메모리 풀, 객체 저장에 사용됩니다.
모든 c/r 프로그램은 기계어 코드로 변환되어야 합니다. 두 가지 프로세스를 통해 완료:
1. 컴파일(Compilation): 전체 코드를 한번에 기계어 코드로 변환하여 컴퓨터에서 실행할 수 있는 바이너리 파일로 작성합니다.
소스 코드 -(컴파일됨)-> 바이너리 코드[이동식 파일] -(실행됨)-> 프로그램 실행
실행은 컴파일 이후에 발생할 수 있습니다.
2. 해석: 통역사는 소스 코드를 실행하고 한 줄씩 실행합니다.
소스코드 -(한줄씩 실행)-> 프로그램 실행
- 여기서 코드는 여전히 기계어 코드로 변환되어야 합니다.
- 컴파일된 l/gs에 비해 속도가 훨씬 느립니다.
3. JIT, 즉 적시 컴파일:
- 최신 JS 엔진은 컴파일과 해석을 혼합하여 빠르게 만듭니다.
- 전체 코드를 한번에 기계어로 변환한 후 즉시 실행합니다.
소스 코드 -(컴파일됨)-> 기계어 -(실행됨)-> 프로그램 실행
- 실행할 중간 이식 파일이 없습니다.
- 컴파일 직후 실행이 발생합니다.
- 따라서 JS는 이 기술 덕분에 해석된 l/gs보다 훨씬 빠릅니다.
JS의 컴파일 프로세스:
1단계. 구문 분석:
- 우리 코드는 구문 분석됩니다. 즉, JS 엔진에서 AST 또는 추상 구문 트리로 읽혀집니다.
- L/G에 의미가 있는 const, let, function 등과 같은 키워드를 기반으로 코드를 트리로 분할하여 작동합니다.
- 그런 다음 코드를 구조화된 방식으로 트리에 저장합니다.
- 구문 오류도 확인하세요.
- AST는 DOM 트리와 아무런 관련이 없습니다. AST는 JS 엔진 내부의 코드를 표현한 것일 뿐입니다.
2, 3단계[결합]: 컴파일 + 실행
- AST는 JIT를 사용하여 컴파일되고 바로 실행됩니다.
- 실행은 호출 스택에서 이루어집니다.
- 최신 JS에는 영리한 최적화 전략이 있습니다. 즉, 최대한 빨리 실행을 시작하기 위해 처음부터 최적화되지 않은 버전의 기계어 코드를 빠르게 생성합니다.
- 백그라운드에서 이 코드는 이미 실행 중인 PGM 실행 중에 다시 컴파일됩니다.
- 여러 번의 반복으로 수행되며 각 최적화 후에는 코드 실행을 중단하지 않고 최적화되지 않은 코드가 새로 최적화된 코드로 교체됩니다. 이것이 V8을 매우 빠르게 만듭니다.
- 이 모든 구문 분석, 컴파일, 실행은 호출 스택을 사용하여 코드를 실행하는 메인 스레드와 완전히 별개인 코드를 사용하여 액세스할 수 없는 JS 엔진 내부의 일부 특수 스레드에서 발생합니다.
- JS는 더 이상 l/g로 해석되지 않습니다. 해석된 l/gs보다 훨씬 빠른 JIT 컴파일이 있습니다.
JS 런타임 = JS 엔진 + 웹 API + C/B 대기열
- JS 런타임: JS를 사용하는 데 필요한 모든 항목이 포함된 컨테이너
- JS 런타임의 핵심은 JS 엔진입니다.
- JS Engine이 없으면 런타임도 없으므로 JS도 전혀 없습니다.
- JS Engine만으로는 충분하지 않습니다. DOM, Fetch, Timers 등과 같은 웹 API에 액세스해야 합니다.
- 웹 API: 런타임에 의해 엔진에 제공되는 기능이지만 JS 엔진의 일부는 아닙니다. 전. 브라우저의 창 개체, 노드의 전역 개체.
- 콜백 큐는 실행할 준비가 된 모든 기능을 포함하는 데이터 구조입니다. 전. 클릭, 타이머, 데이터 등
- DOM 이벤트 핸들러 fns는 콜백 fns라고도 합니다.
- 콜 스택이 비어 있으면 콜백 fn이 C/B 큐에서 호출 스택으로 이동되어 실행됩니다.
- 연속적인 확인과 이동은 Event Loop를 통해 이루어집니다.
- 이벤트 루프는 JS가 비차단 동시성 모델을 가질 수 있게 해주는 것입니다.
- 노드의 경우 브라우저에서 제공하는 Web API가 없습니다. C++ 바인딩 및 스레드 풀이라는 것이 있습니다.
JS 코드가 호출 스택에서 실행되는 방법
- JS에는 단일 실행 스레드가 있으므로 한 번에 작업만 수행할 수 있습니다. 따라서 JS에서는 다중 요청이 없습니다.
- API는 환경에 따라 제공되지만 언어의 일부는 아닙니다. 전. 타이머, 가져오기, DOM, 위치정보 등과 같은 웹 API
- 콜백 대기열: 발생한 일부 이벤트에 첨부된 콜백 fns를 실행할 준비가 되었습니다.
- 콜 스택이 비어 있을 때마다 이벤트 루프는 실행을 위해 콜백을 콜백에서 큐, 호출 스택으로 전달합니다.
- 따라서 이벤트 루프는 JS에서 비동기 동작을 가능하게 하는 필수 요소입니다.
- 동시성 모델: l/g가 동시에 여러 가지 일을 처리하는 방법
- JS 런타임의 필수 부분:
- 콜스택
- 웹 API
- 콜백 대기열
- 이벤트 루프
- DOM과 관련된 모든 것은 JS가 아닌 Web API의 일부입니다.
- 이미지 로딩은 비동기 방식으로 이루어집니다. 동기화 방식이었다면 차단되었을 것입니다. 즉, 메인 스레드가 아닌 Web API 환경에서였을 것입니다.
- 모든 이벤트 리스너, .then() 등의 작업은 호출 스택이 아닌 WEb API 환경에서 발생합니다.
- 콜백 fns는 콜백 스택에서 실행되기를 기다리는 콜백 대기열에 배치됩니다.
- 콜백 큐는 콜 스택이 완료해야 하는 할 일 목록과 같습니다.
- 언급된 기간은 실행 전 최소 지연 시간이지 실행 시간이 아닙니다.
- 콜백 대기열에는 DOM 이벤트, 클릭, 키 누르기 등에서 발생하는 콜백도 포함됩니다. DOM 이벤트는 비동기 동작이 아니지만 실행을 위해 콜백 대기열을 사용합니다.
- 이벤트 루프는 콜백 대기열이 빌 때까지 계속 확인합니다. 콜 스택에 배치된 각 콜백을 이벤트 루프 틱이라고 합니다.
- 이벤트 루프는 전체 JS 런타임을 조정합니다.
- JS는 비동기 코드가 엔진에서 실행되지 않기 때문에 시간 감각이 없습니다. 비동기 동작을 관리하는 런타임과 실행할 콜백을 결정하는 이벤트 루프입니다.
- 엔진 또는 호출 스택은 단순히 주어진 코드를 실행합니다.
- 이미지가 로드될 때 이벤트 리스너는 로드 이벤트가 시작될 때까지 Web API 환경에서 계속 대기합니다. 실행되면 콜백 fn으로 콜백 큐로 이동하여 콜 스택에서 실행될 차례를 기다립니다.
마이크로태스크 대기열:
- Promise의 콜백은 콜백 대기열로 이동하지 않고 마이크로태스크 대기열로 이동합니다.
- 이 대기열은 콜백 대기열보다 우선순위가 높습니다.
- 이벤트 루프는 먼저 이 대기열을 확인하고 모든 작업을 먼저 실행한 다음 실행을 위해 콜백 대기열로 이동합니다.
- Promise에 대한 콜백을 마이크로태스크라고 부르므로 마이크로태스크 대기열이라고 합니다. 다른 마이크로태스크도 있지만 현재로서는 여기에 관련이 없습니다. 이벤트 루프는 각 콜백이 실행되는 시기를 결정합니다. 콜백 대기열에 비해 마이크로태스크에 더 높은 우선순위를 부여합니다
- 마이크로태스크는 다른 모든 일반 콜백 대기열보다 먼저 인라인을 잘라낼 수 있습니다.
- Promise.resolve(): 즉시 해결되는 Promise를 생성하고 그 성공 값이 인수로 전달됩니다. then() 콜백은 확인된 값을 인수로 사용하여 호출됩니다.
console.log("Direct simple console BEGIN");
setTimeout(() => console.log("Text from Timer"),0);
Promise.resolve("Text from Promise").then(res => console.log(res));
console.log("Direct simple console END");
Order of Output:
Direct simple console BEGIN
Direct simple console END
Text from Promise
undefined
Text from Timer
로그인 후 복사
- 마이크로 태스크가 많거나 시간이 많이 걸리는 마이크로 태스크가 있는 경우에도 마이크로 태스크 대기열은 콜백 대기열을 고갈시킬 수도 있습니다.
console.log("Direct simple console BEGIN");
setTimeout(() => console.log("Text from Timer"),0);
Promise.resolve("Text from Promise1").then(res => console.log(res));
Promise.resolve("Text from Promise2").then(res => {
for(let i=0; i<5000; i++)
console.log(res);
});
console.log("Direct simple console END");
로그인 후 복사
위 내용은 자바스크립트 엔진의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!