>  기사  >  웹 프론트엔드  >  js 엔진의 실행 메커니즘에 대한 자세한 설명

js 엔진의 실행 메커니즘에 대한 자세한 설명

小云云
小云云원래의
2018-03-31 17:11:112960검색


이 기사는 모든 사람에게 도움이 되기를 바라며 주로 js 엔진의 실행 메커니즘에 대한 자세한 설명을 공유합니다.

먼저 2가지 사항을 명심하세요:

  • js는 단일 스레드 언어입니다.

  • js의 이벤트 루프는 js의 실행 메커니즘입니다. js 실행에 대한 깊은 이해는 js

의 이벤트 루프에 대한 깊은 이해와 같습니다. js가 단일 스레드인 이유는 무엇인가요?

js는 원래 브라우저에서 사용하도록 설계되었으므로 브라우저의 js가 멀티스레드였다고 상상해 보세요.

시나리오 설명:

이제 process1과 process2라는 2개의 프로세스가 있습니다. 다중 프로세스 js이므로 Process1은 dom을 삭제하고 process2는 dom을 편집하고 문제를 발생시킵니다. 두 가지 모순되는 명령이 있는데, 브라우저는 이를 어떻게 실행해야 할까요?

이렇게 생각해보면 js가 왜 단일 스레드로 설계되었는지 이해하기 쉬울 것입니다.

js에 비동기가 필요한 이유는 무엇인가요?

장면 설명;

js에 비동기가 없으면 위에서 아래로만 실행할 수 있습니다. 이전 줄의 구문 분석 시간이 너무 길면 다음 코드가 차단됩니다. 사용자에게 차단은 '걸림'을 의미하며 이는 사용자 경험을 저하시킵니다.

그래서 js에는 비동기 실행이 있습니다.

단일 스레드는 어떻게 비동기 구현을 달성하나요?

JS는 단일 스레드이고 하나의 스레드에서만 실행될 수 있는데 어떻게 비동기식일 수 있습니까?

JS의 실행 메커니즘을 이해할 수 있는 것은 이벤트 루프(이벤트 루프)입니다.

js

console.log(1);
setTimeout(function() {
  console.log(2);
}, 0);
console.log(3);// 输出 1 3 2

의 이벤트 루프(1) 즉, setTimeout의 함수는 즉시 실행되지 않고 일정 시간 지연된 후 특정 조건이 충족된 후에 실행되는 유형의 코드를 비동기식이라고 합니다. 암호.

여기서 우리는 먼저 작업을 동기 작업과 비동기 작업으로 나누는 JS의 분류 방법을 알고 있습니다.

이 분류 방법에 따르면 js의 실행 메커니즘은 다음과 같습니다.

  • 먼저 js가 동기식 또는 비동기식, 동기화는 메인 스레드에 들어가고, 비동기식은 이벤트 테이블에 들어가고

  • 비동기 작업은 이벤트 테이블에 함수를 등록하고, 트리거 조건이 충족되면 이벤트 큐에 푸시됩니다

  • 동기 작업이 메인 스레드에 진입합니다. 스레드는 메인 스레드가 유휴 상태가 될 때까지 계속 실행됩니다. 그런 다음 실행 가능한 비동기 작업이 있는지 확인하기 위해 이벤트 큐로 이동하여 메인 스레드로 푸시됩니다.

위의 3단계 루프 실행은 이벤트 루프입니다

위 예의 경우 실행 순서를 설명해 주실 수 있나요?

console.log(1); // 同步任务,放入主线程中setTimeout(function() {
  // 异步任务,放到event table中,0秒后被推入到event queue中
  console.log(2);
}, 0);
console.log(3); // 同步任务,放到主线程中// 输出 1 3 2// 当1,3被打印后,主线程去event queue(事件队列)里查看是否有可执行的函数,执行setTimeout里面的函数。

js의 이벤트 루프(2)

다음 예를 살펴보세요.

setTimeout(function() {
  console.log("定时器开始");
}, 0);new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  console.log("执行then函数拉");
});
console.log("代码执行结束");

전에 요약한 js 실행 메커니즘을 사용하여 분석합니다.

setTimeout 是异步任务,放在 event table中new promise是同步任务,被放到主线程中,直接打印console.log('马上执行for循环了');

.then里面的是异步任务,被放到event table中

console.log('代码执行结束') 是同步代码,被放在主线程中,直接执行。

그래서 결과는 [for 루프를 즉시 실행 - 코드 실행 종료 - 타이머가 시작되었습니다 - then 함수가 실행되었습니다]?

직접 실행해 보니 결과는 이렇지 않지만 [for 루프가 즉시 실행됨 - 코드 실행이 종료됨 - then 함수가 실행됨 - 타이머가 시작됨] ]

그렇다면 비동기 작업의 실행 순서는 전후 순서가 아닌 다른 규정이 있는 것이 아닐까요? 사실 비동기와 동기의 구분에 따르면 정확하지 않습니다

정확한 구분은 is:

  • macro-task(macro-task) Task): 전체 코드 스크립트, setTimeout, setInterval

  • micro-task(micro-task): Promise, process, nextTick

js 엔진의 실행 메커니즘에 대한 자세한 설명

에 따르면 이 분류 방법에 따르면 js의 실행 메커니즘은 다음과 같습니다.

  • 매크로 작업을 실행할 때 프로세스 중에 마이크로 작업이 발생하면 현재 매크로 작업이 완료된 후 마이크로 작업의 이벤트 큐에 넣습니다. , 마이크로 태스크의 이벤트 큐가 확인되고 그 안에 있는 모든 마이크로 태스크가 순서대로 완료됩니다.

  • 위의 2단계를 반복하고 이벤트 루프(1) 이벤트 루프(2)를 결합하면 보다 정확한 JS 실행 메커니즘을 얻을 수 있습니다.

  • 지금의 메커니즘에 따르면 예제 2를 분석해 보세요.
// 首先执行script下的宏任务,遇到setTimeout,将其放在宏任务队列中setTimeout(function() {
  console.log("定时器开始");
}, 0);// 遇到new promise直接执行new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  // .then方法,是微任务,放在微任务队列中
  console.log("执行then函数拉");
});
console.log("代码执行结束");// 宏任务执行完毕,查看本轮的微任务,返现有一个then方法。再去执行宏任务队列中的函数。

setTimeout에 대해 이야기하세요

이 setTimeout 코드는 무엇을 의미하나요? 우리는 일반적으로 다음과 같이 말합니다. 3초 후에 setTimeout의 함수가 실행됩니다

setTimeout(function() {
  console.log("执行了");
}, 3000);

그러나 이것은 그렇지 않습니다. true 엄격하고 정확한 설명은 다음과 같습니다. 3초 후에 setTimeout의 함수가 이벤트 큐로 푸시되고 이벤트 큐(이벤트 큐)의 작업은 기본 스레드가 유휴 상태일 때만 실행됩니다.

그래서 (1) 3초 후 (2) 메인 스레드가 유휴 상태이고 둘 다 충족된 경우에만 3초 후에 함수가 실행됩니다.

메인 스레드에서 많은 콘텐츠를 실행하면 실행 시간이 초과됩니다. 3초, 예를 들어 10초면 이 함수는 10초 후에만 실행될 수 있습니다

js 엔진의 실행 메커니즘에 대한 심층적인 이해

먼저 2가지 사항을 명심하세요:

js는 단일 스레드 언어입니다

  • js의 이벤트 루프는 js 실행 메커니즘입니다. js 실행에 대한 깊은 이해는 js

  • 의 이벤트 루프에 대한 깊은 이해와 같습니다. js가 단일 스레드인 이유는 무엇인가요?

  • js는 원래 브라우저에서 사용하도록 설계되었으므로 브라우저의 js가 멀티스레드였다고 상상해 보세요.

장면 설명:

那么现在有 2 个进程,process1 process2,由于是多进程的 js,所以他们对同一个 dom,同时进行操作,process1 删除了该 dom,而 process2 编辑了该 dom,同时下达 2 个矛盾的命令,浏览器究竟该如何执行呢?

这样想,js 为什么被设计成单线程应该就容易理解了吧。

js 为什么需要异步?

场景描述;

如果 js 中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。对于用户而言,阻塞就意味着‘卡死’,这样就导致了很差的用户体验。

所以,js 中存在异步执行。

单线程又是如何实现异步的呢?

既然 JS 是单线程的,只能在一条线程上执行,又是如何实现的异步呢?

是通过的事件循环(event loop), 就理解了 js 的执行机制。

js 中的 event loop(1)

console.log(1);
setTimeout(function() {
  console.log(2);
}, 0);
console.log(3);// 输出 1 3 2

也就是说,setTimeout 里的函数并没有立即执行,而是延迟了一段时间,满足一定条件后,才去执行的,这类代码,我们叫异步代码。

所以,这里我们首先知道了 JS 里的一种分类方式,就是将任务分为: 同步任务和异步任务

按这种分类方式,js 的执行机制就是:

  • 首先判断 js 是同步的还是异步的,同步的就进入主线程,异步就进入 event table

  • 异步任务在 event table 中注册函数,当满足触发条件后,被推入 event queue

  • 同步任务进入主线程后一直执行,直到主线程空闲,才会去 event queue 中查看是否有可执行的异步任务,若果有就推入到主线程中。

以上三步循环执行,就是 event loop

所以上述例子,你是否可以描述他们的执行顺序了?

console.log(1); // 同步任务,放入主线程中setTimeout(function() {
  // 异步任务,放到event table中,0秒后被推入到event queue中
  console.log(2);
}, 0);
console.log(3); // 同步任务,放到主线程中// 输出 1 3 2// 当1,3被打印后,主线程去event queue(事件队列)里查看是否有可执行的函数,执行setTimeout里面的函数。

js 中的 event loop(2)

再看下一个例子:

setTimeout(function() {
  console.log("定时器开始");
}, 0);new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  console.log("执行then函数拉");
});
console.log("代码执行结束");

用之前总结的 js 执行机制去分析:

setTimeout 是异步任务,放在 event table中new promise是同步任务,被放到主线程中,直接打印console.log('马上执行for循环了');

.then里面的是异步任务,被放到event table中

console.log('代码执行结束') 是同步代码,被放在主线程中,直接执行。

所以,结果是 【马上执行 for 循环啦 — 代码执行结束 — 定时器开始啦 — 执行 then 函数啦】吗?

亲自执行后,结果居然不是这样,而是【马上执行 for 循环啦 — 代码执行结束 — 执行 then 函数啦 — 定时器开始啦】

那么,难道是异步任务的执行顺序,不是前后顺序,而是另有规定? 事实上,按照异步和同步的划分方式,并不准确

而准确的划分方式是:

  • macro-task(宏任务): 整体代码 script, setTimeout,setInterval

  • micro-task(微任务): Promise,process,nextTick

js 엔진의 실행 메커니즘에 대한 자세한 설명

按照这种分类方式,js 的执行机制就是:

  • 执行一个宏任务,过程中如果遇到微任务,就将其放到微任务的 event queue 中

  • 当前宏任务执行完成后,会常看微任务的 event queue ,并将里面全部的微任务依次执行完。

重复以上 2 步骤,结合 event loop(1) event loop(2) ,就是更为准确的 JS 执行机制了。

按照刚才的机制,分析例 2:

// 首先执行script下的宏任务,遇到setTimeout,将其放在宏任务队列中setTimeout(function() {
  console.log("定时器开始");
}, 0);// 遇到new promise直接执行new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  // .then方法,是微任务,放在微任务队列中
  console.log("执行then函数拉");
});
console.log("代码执行结束");// 宏任务执行完毕,查看本轮的微任务,返现有一个then方法。再去执行宏任务队列中的函数。

谈谈 setTimeout

这段 setTimeout 代码什么意思? 我们一般说: 3 秒后,会执行 setTimeout 里的那个函数

setTimeout(function() {
  console.log("执行了");
}, 3000);

但是这种说并不严谨,准确的解释是: 3 秒后,setTimeout 里的函数被会推入 event queue,而 event queue(事件队列)里的任务,只有在主线程空闲时才会执行。

所以只有满足 (1)3 秒后 (2)主线程空闲,同时满足时,才会 3 秒后执行该函数

如果主线程执行内容很多,执行时间超过 3 秒,比如执行了 10 秒,那么这个函数只能 10 秒后执行了

위 내용은 js 엔진의 실행 메커니즘에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.