Maison  >  Article  >  interface Web  >  Moteur JavaScript

Moteur JavaScript

WBOY
WBOYoriginal
2024-09-01 21:13:37814parcourir

JavaScript Engine

Moteur JS :

  • Programme qui exécute le code JS. Ex. Le V8 de Google.
  • Le V8 alimente Chrome, Node.js
  • Les autres navigateurs ont leur propre moteur JS.

Le moteur JS comprend 2 parties :

  1. Call Stack : où notre code est exécuté à l'aide du contexte d'exécution.
  2. Heap : pool de mémoire non structurée, utilisé pour stocker des objets.

Chaque programme c/r doit être converti en code machine. Fait via deux processus :

1. Compilation : le code entier est immédiatement converti en code machine, écrit dans un fichier binaire pouvant être exécuté par un ordinateur.

Code source -(compilé)-> Code binaire[Fichier portable] -(exécuté)-> Pgm Run
L'exécution peut avoir lieu bien après la compilation.

2. Interprétation : l'interprète parcourt le code source et l'exécute ligne par ligne.

Code source -(exécution ligne par ligne)-> Pgm Run

  • Ici, le code doit encore être converti en code machine.
  • Ils sont beaucoup plus lents que les l/gs compilés.

3. JIT, c'est-à-dire compilation juste à temps :

  • Modern JS Engine est un mélange de compilation et d'interprétation pour le rendre rapide.
  • Le code entier est converti en code machine en une seule fois, puis exécuté immédiatement. Code source -(compilé)-> Code machine -(exécuté)-> Pgm Run
  • Il n'y a pas de fichier portable intermédiaire à exécuter.
  • L'exécution a lieu immédiatement après la compilation.
  • Par conséquent, JS est désormais beaucoup plus rapide que l/gs interprété grâce à cette technique.

Processus de compilation en JS :

Étape 1. Analyse :

  • Notre code est analysé, c'est-à-dire lu par le moteur JS dans AST ou Abstract Syntax Tree.
  • Fonctionne en divisant le code en un arbre basé sur des mots-clés comme const, let, function, etc. qui sont significatifs pour le l/g.
  • Enregistre ensuite le code dans une arborescence de manière structurée.
  • Vérifiez également les erreurs de syntaxe.
  • AST n'a rien à voir avec l'arborescence DOM. AST n'est qu'une représentation de notre code dans le moteur JS.

Étape 2, 3[combinée] : Compilation + Exécution

  • AST est compilé et exécuté immédiatement après, à l'aide de JIT.
  • L'exécution a lieu dans la pile d'appels.
  • Modern JS a des stratégies d'optimisation intelligentes, c'est-à-dire qu'ils créent rapidement une version non optimisée du code machine au début afin de démarrer l'exécution dès que possible.
  • En arrière-plan, ce code est à nouveau recompilé lors d'une exécution pgm déjà en cours.
  • Fait en plusieurs itérations, et après chaque optimisation, le code non optimisé est remplacé par du code nouvellement optimisé sans jamais arrêter l'exécution du code. Cela rend le V8 si rapide.
  • Toute cette analyse, compilation et exécution se produit dans un thread spécial à l'intérieur de JS Engine auquel nous ne pouvons pas accéder en utilisant notre code complètement séparé du thread principal qui exécute notre code à l'aide de la pile d'appels.
  • JS n'est plus simplement interprété l/g. Il a une compilation JIT qui le rend beaucoup plus rapide que les l/gs interprétés.

JS Runtime = Moteur JS + API Web + file d'attente C/B

  • JS Runtime : conteneur comprenant tout ce dont nous avons besoin pour utiliser JS.
  • Le cœur de tout environnement d'exécution JS est le moteur JS.
  • Sans JS Engine, il n'y a pas de runtime donc pas de JS du tout.
  • Le moteur JS seul ne suffit pas, nous avons besoin d'accéder aux API Web comme DOM, Fetch, Timers, etc.
  • API Web : fonctionnalité fournie au moteur par le moteur d'exécution, mais ne faisant pas partie du moteur JS. Ex. objet window dans le navigateur, objet global dans le nœud.
  • Callback Queue est une structure de données contenant toutes les fonctions prêtes à être exécutées. Ex. clic, minuterie, données, etc
  • Les fns des gestionnaires d'événements DOM sont également appelés fns de rappel.
  • Lorsque la pile d'appels est vide, le rappel fn est déplacé de la file d'attente C/B vers la pile d'appels pour exécution.
  • La vérification et le décalage continus sont effectués par Event Loop.
  • La boucle d'événements est quelque chose qui permet à JS d'avoir un modèle de concurrence non bloquant.
  • Pour le nœud, nous n'avons pas d'API Web fournies par le navigateur. Nous avons quelque chose appelé liaisons C++ et pool de threads.

Comment le code JS s'exécute sur la pile d'appels

  • JS a un seul thread d'exécution et ne peut donc faire qu'une seule chose à la fois. Par conséquent, pas de multi-demandes en JS.
  • Les API sont fournies par l'environnement, mais pas par la partie langage. Ex. API Web comme Timers, Fetch, DOM, Géolocalisation, etc.
  • File d'attente de rappel : fns de rappel prêts à être exécutés qui sont attachés à un événement qui s'est produit.
  • Chaque fois que la pile d'appels est vide, la boucle d'événements transfère le rappel du calback vers la file d'attente pour appeler la pile pour l'exécution.
  • La boucle d'événements est donc un élément essentiel qui rend possible le comportement asynchrone en JS.
  • Modèle de concurrence : comment un l/g gère plusieurs choses qui se produisent en même temps.
  • Parties essentielles de JS Runtime :
  • Pile d'appels
  • API Web
  • File d'attente de rappel
  • Boucle d'événement
  • Tout ce qui concerne le DOM fait partie des API Web, pas du JS.
  • Le chargement de l'image se produit de manière asynchrone, s'il avait été synchronisé, il aurait été bloqué, c'est-à-dire pas sur le thread principal mais plutôt sur l'environnement des API Web.
  • Tous les écouteurs d'événements, .then(), etc., fonctionnent dans l'environnement des API WEb et non sur la pile d'appels.
  • Les fns de rappel sont placés dans la file d'attente de rappel en attendant qu'ils soient exécutés sur la pile d'appels.
  • La file d'attente de rappel est comme une liste de tâches qu'une pile d'appels doit compléter.
  • La durée mentionnée est le délai minimum avant l'exécution, et non le moment de l'exécution.
  • La file d'attente de rappel contient également des rappels provenant d'événements DOM, de clics, de pressions sur une touche, etc. Les événements DOM ne sont pas un comportement asynchrone, mais ils utilisent une file d'attente de rappel pour leur exécution.
  • La boucle d'événements continue de vérifier la file d'attente de rappel jusqu'à ce qu'elle soit vide. Chaque rappel placé sur la pile d'appels est appelé comme tick de boucle d'événement.
  • La boucle d'événements orchestre l'intégralité du runtime JS.
  • JS n'a lui-même aucune notion du temps car le code Async ne s'exécute pas dans le moteur. C'est le runtime qui gère le comportement asynchrone et la boucle d'événements qui décide quel rappel être exécuté.
  • Le moteur ou la pile d'appels exécute simplement le code qui lui est donné.
  • Lorsqu'une image doit être chargée, l'écouteur d'événements continue d'attendre dans l'environnement des API Web jusqu'à ce que l'événement de chargement soit déclenché. Lorsqu'il est déclenché, alors seulement il va dans la file d'attente de rappel en tant que fn de rappel en attendant que son tour soit exécuté sur la pile d'appels.

File d'attente de microtâches :

  • Les rappels des promesses ne vont pas dans la file d'attente des rappels, ils vont dans la file d'attente des microtâches.
  • Cette file d'attente a une priorité plus élevée sur la file d'attente de rappel.
  • La boucle d'événements vérifie d'abord cette file d'attente, exécute d'abord toutes ses tâches, puis va dans la file d'attente de rappel pour exécution.
  • Les rappels sur les promesses sont appelés microtâches, d'où leur nom de file d'attente de microtâches. Il existe également d'autres microtâches, mais elles ne sont pas pertinentes ici pour le moment. La boucle d'événements décide quand chaque rappel est exécuté. Il donne aux microtâches une priorité plus élevée par rapport à la file d'attente de rappel
  • Les microtâches peuvent être coupées en ligne avant toutes les autres files d'attente de rappel régulières.
  • Promise.resolve() : crée une promesse qui est résolue immédiatement et sa valeur de succès y est transmise en argument. Le rappel then() est appelé avec la valeur résolue comme argument.
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
  • Une file d'attente de microtâches peut même affamer la file d'attente de rappel si elle contient beaucoup de microtâches ou des microtâches chronophages.
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");

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn