Ce que cet article vous apporte est un résumé du mécanisme de fonctionnement JavaScript (exemples de code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Avant de parler du mécanisme de fonctionnement javascript, regardons un morceau de code :
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) }) }) })
Si vous voyez ce code et connaissez la séquence de sortie correcte. Cela signifie que vous maîtrisez presque ce domaine. (Allez directement jusqu'à la fin pour voir les résultats)
Bon, passons aux choses sérieuses.
Avant de parler de son fonctionnement, examinons quelques concepts.
Contexte d'exécution
Le contexte d'exécution est simplement un environnement d'exécution. Il a un environnement global, un environnement de fonction et un environnement de fonction d'évaluation. Il sera créé lorsque le moteur JavaScript exécutera votre script.
Pile d'exécution
La pile d'exécution est souvent appelée pile d'appels. C'est une structure de données avec LIFO (dernier entré, premier sorti). Il stocke le contexte d'exécution créé lors de l'exécution du code
Micro-tâches et macro-tâches
Les tâches en JavaScript sont divisées en micro-tâches et macros. Il existe deux types de tâches . Le timing d'exécution de ces deux tâches est différent, il est donc très important de distinguer quelles sont des macro-tâches et lesquelles sont des micro-tâches en js. Nos macro-tâches courantes incluent : les tâches de script, setTimeout, ajax, etc. Les micro-tâches courantes sont plus typiques : Promise.resolve().then(), process.nextTick, MutationObserver, etc.
Boucle d'événements
js est monothread, ce qui signifie qu'il ne peut gérer qu'une seule tâche à la fois. Mais l'environnement hôte dans lequel se trouve js, que nous appelons le navigateur, n'est pas monothread (l'environnement hôte ne parle ici que du navigateur). Lorsqu'il rencontre certaines tâches, telles que setTimeout, l'écouteur d'événements, etc. Il dira au navigateur : Frère, fais-moi une faveur et fais-moi savoir quand ce sera fait, je vais d'abord faire autre chose. Le navigateur répondra : Laissez-moi faire, petit frère. Quand ce sera fait, je le mettrai dans la file d'attente des tâches et le récupérerai moi-même. Ainsi, js commence à exécuter la tâche de script et, une fois l'exécution terminée, il commence à vérifier s'il existe des microtâches. Sinon, il commence à récupérer la macrotâche de la file d'attente des tâches pour l'exécution. Une fois chaque macrotâche exécutée, il vérifie. pour voir s'il y a des microtâches. Si c'est le cas, une fois l'exécution terminée, exécutez à nouveau la tâche macro, et ainsi de suite. Comme suit :
Après avoir compris ces concepts, il sera plus facile et plus agréable de voir comment javascript exécute le code. Commençons
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) }) }) })
Lorsque le moteur js exécute ce code, il pousse d'abord le contexte d'exécution global sur la pile :
Puis, lors de l'exécution, vous rencontrerez la fonction console.log et la pousserez sur la pile :
À ce moment, exécutez-la directement fonction console et sortie 1. Ensuite, la fonction console sort de la pile :
Continuez à exécuter, rencontrez Promise.resolve().then(), changez d'abord Promise.resolve ( ).then() est poussé sur la pile (ici, je le considère dans son ensemble pour la commodité du dessin, sinon je devrais dessiner beaucoup d'images).
Ensuite, exécutez Promise.resolve().then() Comme mentionné précédemment, cette fonction then() est une microtâche et elle transmettra la fonction de rappel qui lui est transmise. . Rejoignez la file d'attente des microtâches.
Ensuite, Promise.resolve().then() sort de la pile.
Ensuite, exécutez et rencontrez le constructeur de promise. Ce constructeur est une tâche macro et poussera directement la fonction qui lui est transmise sur la pile.
Exécutez la fonction console et sortez 3. Après l'exécution, la fonction console est extraite de la pile, puis la fonction solve() est exécutée et extraite de la pile.
Continuez ensuite à exécuter la fonction then et placez la fonction paramètre passée à la fonction then dans la file d'attente des microtâches :
Continuez, continuez va Exécuter ci-dessous. Lorsque vous rencontrez console.log(6), sans dire un mot, il est directement poussé dans la pile, exécuté, génère 6 et sort de la pile, le tout en une seule fois.
接着,引擎碰到了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。你写对了了吗?
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!