Le typographie transpire vers JS. Ensuite, il y a la secousse d'arbre, "moins" (facultatif) et quoi d'autre dans le processus de déploiement. Mais rien de tout cela (afaik) n'a rien à voir avec la "compilation". Tout est regroupé et fortement optimisé, mais ce n'est pas vraiment compilé, non?
La compilation consiste à transformer un programme écrit dans un langage A en un programme sémantiquement équivalent écrit en langage B tel qu'évaluer le programme compilé selon les règles du langage B (par exemple l'interpréter avec un interpréteur pour B ) donne le même résultat et a le mêmes effets secondaires que l'évaluation du programme original selon les règles du langage A (par exemple l'interpréter avec un interprète pour A ).
Compilation signifie simplement la traduction d' un programme de langue A à la langue B . C'est tout ce que cela signifie. (Notez également qu'il est parfaitement possible que A et B soient la même langue.)
Dans certains cas, nous avons des noms plus spécialisés pour certains types de compilateurs, selon ce que sont A et B et ce que fait le compilateur:
- si A est perçu comme un langage d'assemblage et B est perçu comme un langage machine, alors nous l'appelons un assembleur ,
- si A est perçu comme un langage machine et B est perçu comme un langage d'assemblage, alors nous l'appelons un désassembleur ,
- si A est perçu comme étant de niveau inférieur à B , alors nous l'appelons un décompilateur ,
- si A et B sont le même langage et que le programme résultant est en quelque sorte plus rapide ou plus léger, nous l'appelons un optimiseur ,
- si A et B sont les mêmes langages et que le programme résultant est plus petit, alors nous l'appelons un minifier ,
- si A et B sont les mêmes langages et que le programme résultant est moins lisible, alors on l'appelle un obfuscator ,
- si A et B sont perçus comme étant à peu près au même niveau d'abstraction, alors nous l'appelons un transpilateur , et
- si A et B sont perçus comme étant à peu près au même niveau d'abstraction et que le programme résultant préserve le formatage, les commentaires et l'intention du programmeur de sorte qu'il soit possible de maintenir le programme résultant de la même manière que le programme d'origine, alors nous appelons c'est un outil de réingénierie .
Notez également que les sources plus anciennes peuvent utiliser les termes «traduction» et «traducteur» au lieu de «compilation» et «compilateur». Par exemple, C parle d '«unités de traduction».
Vous pouvez également tomber sur le terme «processeur de langage». Cela peut signifier soit un compilateur, un interpréteur, ou les deux compilateurs et interprètes selon la définition.
Javascript lui-même est toujours interprété, non?
JavaScript est un langage. Les langues sont un ensemble de règles logiques et de restrictions. Les langues ne sont ni interprétées ni compilées. Les langues sont juste .
La compilation et l'interprétation sont des traits d'un compilateur ou d'un interprète (duh!). Chaque langage peut être implémenté avec un compilateur et chaque langage peut être implémenté avec un interpréteur. De nombreux langages ont à la fois des compilateurs et des interprètes. De nombreux moteurs d'exécution modernes hautes performances ont à la fois au moins un compilateur et au moins un interpréteur.
Ces deux termes appartiennent à des couches d'abstraction différentes. Si l'anglais était une langue typée, «interprété-langue» serait une erreur de type.
Notez également que certains langages n'ont ni interpréteur ni compilateur. Il existe des langages qui n'ont pas du tout d'implémentation. Pourtant, ce sont des langages et vous pouvez y écrire des programmes. Vous ne pouvez tout simplement pas les exécuter.
Notez également que tout est interprété à un moment donné : si vous voulez exécuter quelque chose, vous devez l' interpréter. La compilation traduit simplement le code d'une langue à une autre. Il ne le fait pas fonctionner. L'interprétation le dirige. (Parfois, lorsqu'un interpréteur est implémenté dans le matériel, nous l'appelons un "CPU", mais c'est toujours un interpréteur.)
Exemple concret: chaque implémentation JavaScript grand public actuellement existante a un compilateur.
V8 a commencé comme un pur compilateur: il a compilé JavaScript directement en code machine natif modérément optimisé. Plus tard, un deuxième compilateur a été ajouté. Maintenant, il existe deux compilateurs: un compilateur léger qui produit du code moyennement optimisé mais le compilateur lui-même est très rapide et utilise peu de RAM. Ce compilateur injecte également du code de profilage dans le code compilé. Le deuxième compilateur est un compilateur plus lourd, plus lent et plus cher, qui, cependant, produit un code beaucoup plus serré et beaucoup plus rapide. Il utilise également les résultats du code de profilage injecté par le premier compilateur pour prendre des décisions d'optimisation dynamique. En outre, la décision du code à recompiler à l'aide du deuxième compilateur est prise en fonction de ces informations de profilage. Notez qu'à aucun moment il n'y a d'interprète impliqué. Le V8 n'interprète jamais, il compile toujours. C'est pas ca' t même contenir un interprète. (En fait, je crois que c'est le cas aujourd'hui, je décris les deux premières itérations.)
SpiderMonkey compile JavaScript en bytecode SpiderMonkey, qu'il interprète ensuite. L'interpréteur profile également le code, puis le code qui est exécuté le plus souvent est compilé par un compilateur en code machine natif. Ainsi, SpiderMonkey contient deux compilateurs: un de JavaScript au bytecode SpiderMonkey, et un autre du bytecode SpiderMonkey au code machine natif.
Presque tous les moteurs d'exécution JavaScript (à l'exception de V8) suivent ce modèle d'un compilateur AOT qui compile JavaScript en bytecode, et un moteur en mode mixte qui bascule entre l'interprétation et la compilation de ce bytecode.
Vous avez écrit dans un commentaire:
Je pensais vraiment que le code machine est quelque part impliqué.
Que signifie même «code machine»?
Qu'est-ce que le langage machine d'un homme est le langage intermédiaire d'un autre homme et vice versa? Par exemple, il existe des processeurs qui peuvent exécuter nativement le bytecode JVM, sur un tel processeur, le bytecode JVM est un code machine natif. Et il y a des interpréteurs pour le code machine x86, lorsque vous exécutez ces codes machine x86 est interprété bytecode.
Il existe un interpréteur x86 appelé JPC écrit en Java. Si j'exécute du code machine x86 sur JPC fonctionnant sur un processeur JVM natif… quel est le bytecode et quel est le code natif? Si je compile du code machine x86 en JavaScript (oui, il existe des outils qui peuvent le faire) et que je l'exécute dans un navigateur sur mon téléphone (qui dispose d'un processeur ARM), quel est le bytecode et quel est le code machine natif? Que faire si le programme que je compile est un émulateur SPARC et que je l'utilise pour exécuter du code SPARC?
Notez que chaque langage induit une machine abstraite, et est un langage machine pour cette machine. Ainsi, chaque langue (y compris les langues de très haut niveau) est un code machine natif. En outre, vous pouvez écrire un interprète pour chaque langue. Ainsi, chaque langue (y compris le code machine x86) n'est pas native.