Maison > Article > interface Web > Introduction détaillée au mécanisme d'exploitation JavaScript (exemple de code)
Cet article vous apporte une introduction détaillée (exemple de code) sur le Mécanisme d'exécution de JavaScript , qui a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. , j'espère que cela vous sera utile.
1. Introduction
Cet article présente le mécanisme de fonctionnement de JavaScript. Cette partie est relativement abstraite :
console.log(1); setTimeout(function(){ console.log(3); },0); console.log(2); 请问数字打印顺序是什么? 复制代码Cette question peut sembler simple, mais si vous ne comprenez pas comment fonctionne JavaScript, il est facile de se tromper de réponse. La réponse à la question est de sortir 1 2 3 dans l'ordre. Si vous avez des doutes, vous trouverez une explication détaillée ci-dessous.
2. Comprendre le concept de single-threading en JS
Une fonctionnalité majeure du langage JavaScript est le single-threading, c'est-à-dire qu'une seule chose peut être fait en même temps. Alors pourquoi JavaScript ne peut-il pas avoir plusieurs threads ? Cela peut améliorer l’efficacité. JavaScript est monothread, selon son objectif. En tant que langage de script de navigateur, l'objectif principal de JavaScript est d'interagir avec les utilisateurs et de manipuler le DOM. Cela détermine qu'il ne peut être qu'un seul thread, sinon cela entraînera des problèmes de synchronisation très complexes. Par exemple, supposons que JavaScript ait deux threads en même temps. Un thread ajoute du contenu à un certain nœud DOM et l'autre thread supprime le nœud. Dans ce cas, quel thread le navigateur doit-il utiliser ? Par conséquent, afin d'éviter toute complexité, JavaScript est monothread depuis sa naissance. Cela est devenu une fonctionnalité essentielle du langage et ne changera pas à l'avenir.3. Comprendre la file d'attente des tâches (file d'attente des messages)
Un seul thread signifie que toutes les tâches doivent être mises en file d'attente et que la tâche précédente sera terminée avant que la tâche suivante ne soit terminée. exécuté. Si la tâche précédente prend beaucoup de temps, la tâche suivante devra attendre. Les concepteurs du langage JavaScript ont réalisé ce problème et ont divisé toutes les tâches en deux types, l'une est une tâche synchrone (synchrone) et l'autre est une tâche asynchrone (asynchrone). Les tâches synchrones font référence aux tâches mises en file d'attente pour exécution sur le thread principal. La tâche suivante ne peut être exécutée qu'après l'exécution de la tâche précédente ; les tâches asynchrones font référence aux tâches qui n'entrent pas dans le thread principal mais entrent dans la « file d'attente des tâches ». Ce n'est que lorsque la « file d'attente des tâches » informe le thread principal qu'une tâche asynchrone peut être exécutée que la tâche entrera dans le thread principal pour exécution. Les tâches asynchrones incluent les macro-tâches et les micro-tâches (qui seront mises en évidence plus tard). Ensuite, nous illustrerons la différence entre les tâches synchrones et les tâches asynchrones à travers deux exemples :console.log("A"); while(true){ } console.log("B"); 请问最后的输出结果是什么? 复制代码Si votre réponse est A, félicitations pour la bonne réponse. Comme il s'agit d'une tâche synchrone, le programme est exécuté de haut en bas. Lorsque vous rencontrez la boucle infinie while(), l'instruction suivante ne peut pas être exécutée
console.log("A"); setTimeout(function(){ console.log("B"); },0); while(true){} 请问最后的输出结果是什么? 复制代码Si votre réponse est A, félicitations pour votre compréhension de js, maintenant j'ai déjà une compréhension approximative du mécanisme de fonctionnement ! Le setTimeout() dans la question est une tâche asynchrone.
Aucune tâche asynchrone ne sera exécutée tant que toutes les tâches synchrones ne seront pas exécutées Cela sera expliqué en détail ci-dessous.
4. Comprendre la boucle d'événements
Le mécanisme de fonctionnement de l'exécution asynchrone est le suivant :Le thread principal lit les événements de la "file d'attente des tâches". Ce processus est cyclique, donc l'ensemble du mécanisme de fonctionnement est également appelé Event Loop. Tant que le thread principal est vide, il lira la "file d'attente des tâches". C'est le mécanisme d'exécution de JavaScript. Ce processus se répétera encore et encore. L’image ci-dessous illustre bien ce point.
5. Quelles instructions seront mises dans la file d'attente des tâches asynchrones et quand les mettre
De manière générale, il y a les quatre types d'instructions suivants placés dans la file d'attente des tâches asynchrones :javascript 代码运行分两个阶段:
1、预解析---把所有的函数定义提前,所有的变量声明提前,变量的赋值不提前
2、执行---从上到下执行(按照js运行机制) 至于放入异步任务队列的时机,我们通过 setTimeout的例子和Ajax例子来详细说明:
例题1 for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 1000); } 请问最后的输出结果是什么? 复制代码
for循环一次碰到一个 setTimeout(),并不是马上把setTimeout()拿到异步队列中,而要等到一秒后,才将其放到任务队列里面,一旦"执行栈"中的所有同步任务执行完毕(即for循环结束,此时i已经为5),系统就会读取已经存放"任务队列"的setTimeout()(有五个),于是答案是输出5个5。
上面也提到,在到达指定时间时,定时器就会将相应回调函数插入“任务队列”尾部。这就是“定时器(timer)”功能。 关于定时器的重要补充:
定时器包括setTimeout与 setInterval 两个方法。它们的第二个参数是指定其回调函数推迟/每隔多少毫秒数后执行。
对于第二个参数有以下需要注意的地方:
当第二个参数缺省时,默认为 0;
当指定的值小于 4 毫秒,则增加到 4ms(4ms 是 HTML5 标准指定的,对于 2010 年及之前的浏览器则是 10ms);也就是说至少需要4毫秒,该setTimeout()拿到任务队列中。
例题2 $.ajax({ url:'xxxxx', success:function (result){ console.log("a") } }) setTimeout(function (){ console.log("b") },100) setTimeout(function (){ console.log("c") }) console.log("d");
ajax加载完成时才会放入异步队列,至于这段时间不确定,所有有两种情况:①大于100ms,最后的结果是 d c b a ;②小于100ms,最后的结果便是d c a b。
六、微任务(Microtask)与宏任务(Macrotask)
我们上面提到异步任务分为宏任务和微任务,宏任务队列可以有多个,微任务队列只有一个。
当执行栈中的所有同步任务执行完毕时,是先执行宏任务还是微任务呢?
一句话概括上面的流程图:当某个宏任务队列的中的任务全部执行完以后,会查看是否有微任务队列。如果有,先执行微任务队列中的所有任务,如果没有,就查看是否有其他宏任务队列。
接下来我们看两道例子来介绍上面流程:
Promise.resolve().then(()=>{ console.log('Promise1') setTimeout(()=>{ console.log('setTimeout2') },0) }) setTimeout(()=>{ console.log('setTimeout1') Promise.resolve().then(()=>{ console.log('Promise2') }) },0) 复制代码
最后输出结果是Promise1,setTimeout1,Promise2,setTimeout2
console.log('----------------- start -----------------'); setTimeout(() => { console.log('setTimeout'); }, 0) new Promise((resolve, reject) =>{ for (var i = 0; i < 5; i++) { console.log(i); } resolve(); // 修改promise实例对象的状态为成功的状态 }).then(() => { console.log('promise实例成功回调执行'); }) console.log('----------------- end -----------------');
七、题外话
如果要输出0~4,上面例题应该如何修改?
for (let i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 1000); } 复制代码
for (var i = 0; i < 5; i++) { (function(i){ setTimeout(function() { console.log(i); }, 1000); })(i) } 复制代码
for(var i = 1;i < 5;i++){ var a = function(){ var j = i; setTimeout(function(){ console.log(j); },1000) } a(); }
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!