이 글은 특정 참고 가치가 있는 JavaScript 작동 메커니즘(코드 예제)을 요약한 것입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
자바스크립트 실행 메커니즘에 대해 이야기하기 전에 코드를 살펴보겠습니다.
console.log(1) Promise.resolve().then(function () { console.log(2) }) new Promise(function(resolve, reject){ console.log(3) resolve() }).then(function () { console.log(4) setTimeout(function () { console.log(5) }) }) console.log(6) setTimeout(function () { Promise.resolve().then(function () { console.log(7) setTimeout(function () { console.log(8) }) }) })
이 코드를 보고 올바른 출력 순서를 알고 있다면. 이는 당신이 이 영역을 거의 마스터했다는 것을 의미합니다. (결과는 바로 끝까지 가셔서 확인하세요)
자, 다시 본론으로 돌아가겠습니다.
작동 방식에 대해 이야기하기 전에 몇 가지 개념을 살펴보겠습니다.
실행 컨텍스트
실행 컨텍스트는 단순히 실행 환경입니다. 글로벌 환경, 함수 환경, 평가 함수 환경이 있습니다. JavaScript 엔진이 스크립트를 실행할 때 생성됩니다.
실행 스택
실행 스택은 일반적으로 호출 스택이라고도 합니다. LIFO(후입선출)를 사용한 데이터 구조입니다. 코드가 실행될 때 생성된 실행 컨텍스트를 저장합니다
마이크로 태스크와 매크로 태스크
자바스크립트의 태스크는 마이크로 태스크와 매크로 태스크의 두 가지 유형으로 나누어지는데, 이 두 태스크의 실행 시점이 다르기 때문에 매우 중요합니다. js에서 매크로 작업과 마이크로 작업을 구별합니다. 일반적인 매크로 작업에는 스크립트 작업, setTimeout, ajax 등이 포함됩니다. 일반적인 마이크로 작업에는 일반적으로 Promise.resolve().then(), process.nextTick, MutationObserver 등이 있습니다.
이벤트 루프
js는 단일 스레드이므로 한 번에 하나의 작업만 처리할 수 있습니다. 하지만 우리가 브라우저라고 부르는 js가 위치한 호스트 환경은 단일 스레드가 아닙니다(호스트 환경은 여기에서 브라우저에 대해서만 설명합니다). setTimeout, 이벤트 리스너 등과 같은 일부 작업이 발생할 때 그것은 브라우저에게 다음과 같이 말할 것입니다: 형님, 부탁 하나만 들어주시고, 일이 끝나면 다른 일을 먼저 하도록 할게요. 브라우저는 다음과 같이 응답할 것입니다: 나에게 맡겨라, 동생아. 완료되면 내가 작업 대기열에 넣고 직접 가져갈 것이다. 그래서 js는 스크립트 작업을 실행하기 시작하고, 실행이 완료된 후 마이크로태스크가 있는지 확인하기 시작합니다. 그렇지 않은 경우에는 실행을 위해 작업 대기열에서 매크로태스크를 가져오기 시작합니다. 마이크로 작업이 있는지 확인하십시오. 그렇다면 실행이 완료되면 매크로 작업을 다시 실행하십시오.
이러한 개념을 이해하고 나면 자바스크립트가 코드를 어떻게 실행하는지 보는 것이 더 쉽고 재미있을 것입니다. 시작하겠습니다
console.log(1) Promise.resolve().then(function () { console.log(2) }) new Promise(function(resolve, reject){ console.log(3) resolve() }).then(function () { console.log(4) setTimeout(function () { console.log(5) }) }) console.log(6) setTimeout(function () { Promise.resolve().then(function () { console.log(7) setTimeout(function () { console.log(8) }) }) })
js 엔진이 이 코드를 실행할 때 먼저 전역 실행 컨텍스트를 스택에 푸시합니다.
그런 다음 실행 중에 console.log 함수를 만나 푸시합니다. the stack:
이때 콘솔 기능이 직접 실행되어 1이 출력됩니다. 그런 다음 콘솔 함수가 스택에서 나타납니다.
계속 실행하고 Promise.resolve().then()을 만나 먼저 Promise.resolve().then()을 스택에 푸시합니다(여기서는 그림의 편의를 위해 전체적으로 고려하십시오. 그렇지 않으면 많은 그림을 그려야합니다).
그런 다음 Promise.resolve().then()을 실행합니다. 앞서 언급했듯이 이 then() 함수는 마이크로태스크 대기열에 전달된 콜백 함수를 추가합니다.
Then Promise.resolve().then()이 스택에서 튀어나옵니다.
그런 다음 Promise의 생성자를 실행하고 만나십시오. 이 생성자는 매크로 작업이며 전달된 함수를 스택에 직접 푸시합니다.
콘솔 함수 실행 및 출력 3. 실행 후 콘솔 함수가 스택에서 팝되고, 그 다음에는solve() 함수가 실행되어 스택에서 팝됩니다.
그런 다음 then 함수를 계속 실행하고 then 함수에 전달된 매개변수 함수를 마이크로태스크 대기열에 넣습니다.
계속 실행합니다. console.log(6)을 만나면 아무 말도 하지 않고 직접 스택에 푸시되고, 실행되고, 6을 출력하고, 스택에서 튀어나옵니다. 이 모든 것이 한꺼번에 이루어집니다.
接着,引擎碰到了setTimeout函数,这家伙是个宏任务,但同时它会将传递给它的函数,加入到任务队列中:
好了,到此第一波宏任务就全部执行完毕。接着,引擎就会去看一下微任务队列中有没有任务,如果有的话,执行它们。
现在看到的是,微任务队列中有两个任务。按照队列的先入先出规则,先从function () {console.log(2)}开始执行。先是函数入栈,然后执行函数,输出2,然后函数出栈。
接着执行下面这段代码:
console.log(4) setTimeout(function () { console.log(5) })
先从console.log(4)开始,先将它入栈,然后执行它,输出4,然后函数出栈。
接着执行:
setTimeout(function () { console.log(5) })
将
function () { console.log(5) }
加入到任务队列中去
先执行:
function(){ Promise.resolve().then(function () { console.log(7) setTimeout(function () { console.log(8) }) }) }
这里执行这个函数的时候遇到一个微任务,将这个微任务添加到微任务队列,如下:
这批次的宏任务就执行完毕了,接着就回去检查微任务队列中有没有待执行的任务。一看还真有两个小可爱等待执行,于是没什么好说的,直接拧出去就执行
先是执行console.log(7),然后输出7。接着执行setTimeout,将传递给他的任务添加到任务队列中去:
最后就剩这两个函数了,按照队列的先入后出一次执行吧,输出5和8。
好了,最后的结果就是1,3,6,2,4,7,5,8。你写对了了吗?
위 내용은 JavaScript 작동 메커니즘 요약(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!