Programmation JavaScript/Ordre d'évaluation
Scripts
modifierLors du chargement d'une page Web, dès que le navigateur rencontre un script, il l'exécute avant de charger la suite du document HTML. Si le script contient des instructions qui doivent être évaluées immédiatement et qui manipulent le document, ce dernier risque de ne pas être prêt.
Lorsque des balises <script>
possèdent l'attribut defer
, le navigateur est supposé télécharger ces scripts en parallèle (donc plus rapidement), et attendre d'avoir fini le chargement de la page avant de les exécuter dans l'ordre des balises.
Lorsque qu'elles possèdent l'attribut async
, le navigateur les télécharge et exécute en parallèle, dans un ordre qui dépend du contexte, donc aléatoire et potentiellement avant la fin du chargement de la page. Il ne faut donc jamais l'utiliser pour charger des bibliothèques ayant des dépendances, comme jQuery.
S'il faut manipuler le document au moment du chargement, il est donc fortement recommandé de déclencher le code après avoir déclaré toute partie du document qui doit être utilisée. Il reste bien sûr possible de déclarer la plupart du code dans des fonctions avant le corps du document, comme cela est fait couramment, et soit d'appeler les fonctions dans un script ultérieur, soit de placer ces instructions dans la méthode document.onload
.
Instructions
modifierÀ la base, chaque fichier ou fragment de code JavaScript est évalué de haut en bas : chaque instruction est exécutée avant de passer à la suivante. Bien entendu, les fonctions, structures de contrôle, et d'autres éléments du langage font que certaines instructions sont évaluées à un autre moment, et/ou plusieurs fois, ou pas du tout.
Expressions
modifierLes expressions sont évaluées de gauche à droite, en respectant la priorité des opérateurs et les parenthèses. Lorsqu'une expression est composée d'opérations de priorité identique (par exemple, plusieurs additions) la première opération en partant de la gauche est effectuée (et ses opérandes sont évaluées), puis son résultat est utilisé comme opérande de gauche de l'opération suivante (et l'opérande de droite est évaluée), et ainsi de suite.
str = 1 + 3 + "5" + -1 + 2
alert( str ) // affiche "45-12"
L'exemple ci-dessus montre que la première opération entre deux nombres se comporte normalement (1 et 3 font 4), la seconde se transforme en concaténation car une des opérandes est de type "string", et à partir de là le résultat de chaque opération est une chaîne donc toutes les additions suivantes se transforment en concaténations. Ce serait différent avec des parenthèses :
str = 1 + 3 + "5" + (-1 + 2)
alert( str ) // affiche "451"
Les opérations de priorité identique ne sont pas évaluées simultanément (techniquement ce ne serait pas possible d'ailleurs) et marginalement, cela peut avoir une influence sur le résultat. Par conséquent, les opérations que l'on appelle commutatives en mathématiques ne sont pas strictement commutatives en JavaScript.
u = v + (v = u) // équivalent à trois instructions séparées pour calculer la suite de Fibonacci
// est différent de :
u = (v = u) + v // façon tordue d'écrire u*=2
Dans cet exemple, l'addition n'est pas commutative. Si l'opération v=u est placée à gauche de l'addition, elle est évaluée en premier et modifie l'autre opérande. En revanche, placée à droite, elle est évaluée après v, et donc la valeur de v utilisée par l'addition est l'ancienne valeur.