Auparavant, nous avons exploré le principe de fonctionnement de JavaScript à partir du mécanisme d'analyse du moteur JavaScript. Nous utilisons maintenant un exemple plus frappant pour illustrer l'ordre d'exécution du code JavaScript sur la page. Si le mécanisme de fonctionnement du moteur JavaScript est relativement profond car il appartient au comportement sous-jacent, alors l'ordre d'exécution du code JavaScript est plus vivant, car nous pouvons ressentir intuitivement cet ordre d'exécution. Bien sûr, l'ordre d'exécution du code JavaScript. est relativement complexe, il est donc également nécessaire de profiler le langage JavaScript avant de s'y plonger.
1.1 Exécuter du code JavaScript dans l'ordre du flux de documents HTML
Tout d'abord, les lecteurs doivent savoir que le processus d'analyse des documents HTML dans le navigateur est le suivant : le navigateur analyse progressivement la structure de la page et les informations de haut en bas en fonction du flux du document. Le code JavaScript en tant que script intégré doit également être considéré comme un composant du document HTML, de sorte que l'ordre d'exécution du code JavaScript lors du chargement est également déterminé en fonction de l'ordre dans lequel la balise de script <script> apparaît. Par exemple, parcourez la page de documentation ci-dessous et vous verrez que le code est analysé étape par étape de haut en bas.
Copiez le code comme suit :
<script>
alert("Script supérieur");
</script>
<html><tête>
<script>
alert("script principal");
</script>
<titre></titre>
</tête>
<corps>
<script>
alerte("script de la page");
</script>
</body></html>
<script>
alert("script du bas");
</script>
Si un script de fichier JavaScript externe est importé via l'attribut src de la balise de script <script>, il sera également exécuté dans l'ordre dans lequel ses instructions apparaissent, et le processus d'exécution fait partie du chargement du document. L'exécution ne sera pas retardée car il s'agit d'un fichier JavaScript externe. Par exemple, déplacez les scripts dans les zones d'en-tête et de corps du document ci-dessus vers des fichiers JavaScript externes, puis importez-les via l'attribut src. En continuant à prévisualiser la page du document, vous verrez le même ordre d'exécution.
Copiez le code comme suit :
<script>
alert("Script supérieur");
</script>
<html>
<tête>
<script src="//www.VeVB.COm/head.js"></script>
<titre></titre>
</tête>
<corps>
<script src="//www.VeVB.COm/body.js"></script>
</corps>
</html>
<script>
alert("script du bas");
</script>
1.2 Relation entre précompilation et ordre d'exécution
En Javascript, la fonction est le premier type de Javascript. Lorsque nous écrivons une fonction, nous créons simplement une entité de type fonction.
Tout comme on peut l'écrire sous cette forme :
Copiez le code comme suit :
fonctionBonjour()
{
alert("Bonjour");
}
Bonjour();
varBonjour = fonction()
{
alert("Bonjour");
}
Bonjour();
En fait, ils sont tous pareils. Mais lorsque nous modifions les fonctions, nous trouverons des problèmes très étranges.
Copiez le code comme suit :
<scripttype="text/javascript">
fonctionBonjour() {
alert("Bonjour");
}
Bonjour();
fonctionBonjour() {
alert("Bonjour tout le monde");
}
Bonjour();
</script>
Nous verrons le résultat comme ceci : Hello World est affiché deux fois de suite.
Plutôt que le Hello et le Hello World que nous imaginions.
En effet, Javascript n'est pas complètement interprété et exécuté dans l'ordre. Au lieu de cela, Javascript est "précompilé" avant l'interprétation. Pendant le processus de précompilation, les fonctions définies seront exécutées en premier et toutes les variables var seront créées, la valeur par défaut n'est pas définie pour améliorer. efficacité de l'exécution du programme.
En d’autres termes, le morceau de code ci-dessus est en fait pré-compilé par le moteur JS sous cette forme :
Copiez le code comme suit :
<scripttype="text/javascript">
varBonjour = fonction() {
alert("Bonjour");
}
Bonjour = fonction() {
alert("Bonjour tout le monde");
}
Bonjour();
Bonjour();
</script>
Nous pouvons clairement voir à partir du code ci-dessus que les fonctions sont également des données et des variables. Nous pouvons également attribuer (réaffecter) des valeurs aux « fonctions ».
Bien entendu, afin d’éviter cette situation, nous pouvons également procéder ainsi :
Copiez le code comme suit :
<scripttype="text/javascript">
fonctionBonjour() {
alert("Bonjour");
}
Bonjour();
</script>
<scripttype="text/javascript">
fonctionBonjour() {
alert("Bonjour tout le monde");
}
Bonjour();
</script>
De cette façon, le programme est divisé en deux sections et le moteur JS ne les rassemblera pas.
Lorsque le moteur JavaScript analyse un script, il traite toutes les variables et fonctions déclarées lors de la précompilation.
Procédez comme suit :
1. Avant l'exécution, une opération similaire à la « précompilation » sera effectuée : d'abord, un objet actif dans l'environnement d'exécution actuel sera créé, et les variables déclarées avec var seront définies comme attributs de l'objet actif, mais à ce moment , l'affectation de ces variables sera indéfinie, et les fonctions définies avec function sont également ajoutées en tant que propriétés de l'objet actif, et leurs valeurs sont exactement la définition de la fonction.
2. Pendant la phase d'interprétation et d'exécution, lorsqu'une variable doit être analysée, elle sera d'abord recherchée à partir de l'objet actif de l'environnement d'exécution actuel. Si elle n'est pas trouvée et que le propriétaire de l'environnement d'exécution possède l'attribut prototype, elle est utilisée. sera recherché à partir de la chaîne de prototypes, sinon il sera recherché en fonction de la chaîne de portée. Lorsque vous rencontrez une instruction telle que var a = ..., la variable correspondante se verra attribuer une valeur (remarque : l'affectation de la variable est terminée pendant la phase d'interprétation et d'exécution. Si la variable est utilisée avant cela, sa valeur sera non défini). Par conséquent, il apparaîtra simplement qu'aucune erreur ne sera signalée lorsque l'interpréteur JavaScript exécute le script suivant :
Copiez le code comme suit :
alert(a); // valeur de retour non définie
var a = 1 ;
alert(a); // renvoie la valeur 1
Étant donné que les déclarations de variables sont traitées au moment de la précompilation, elles sont visibles par tout le code pendant l'exécution. Cependant, vous verrez également que lors de l'exécution du code ci-dessus, la valeur demandée est indéfinie et non 1. En effet, le processus d'initialisation des variables se produit lors de l'exécution et non lors de la pré-compilation. Lors de l'exécution, l'interpréteur JavaScript analyse le code dans l'ordre. Si aucune valeur n'est attribuée à une variable dans la ligne de code précédente, l'interpréteur JavaScript utilisera la valeur par défaut non définie. Étant donné qu'une valeur est attribuée à la variable a dans la deuxième ligne, la troisième ligne de code indiquera que la valeur de la variable a est 1, et non indéfinie.
De même, dans l'exemple suivant, il est légal d'appeler la fonction avant qu'elle ne soit déclarée et puisse être analysée correctement, donc la valeur de retour est 1.
Copiez le code comme suit :
f(); // Appel de la fonction, renvoie la valeur 1
fonction f(){
alerte(1);
}
Cependant, si la fonction est définie comme suit, l'interpréteur JavaScript générera une erreur de syntaxe.
Copiez le code comme suit :
f(); // Appel de la fonction et renvoie une erreur de syntaxe
var f = fonction(){
alerte(1);
}
En effet, la fonction définie dans l'exemple ci-dessus n'est affectée qu'à la variable f en tant que valeur. Par conséquent, pendant la période de pré-compilation, l'interpréteur JavaScript ne peut traiter que la déclaration de la variable f, et la valeur de la variable f ne peut traiter que la valeur de la variable f. être enfoncé pendant la période d'exécution. Si les affectations sont effectuées séquentiellement, une erreur de syntaxe se produira naturellement, indiquant que l'objet f est introuvable.
Au revoir quelques exemples :
Copiez le code comme suit :
<script type="text/javascript">
/*Pendant le processus de précompilation, func est un attribut de l'objet actif dans l'environnement de fenêtre, et la valeur est une fonction, couvrant la valeur non définie*/
alerte(func); //fonction func(){alerte("bonjour!")}
var func = " ceci est une variable "
fonction fonction(){
alerte("Bonjour!")
}
/*Pendant l'exécution, var a été rencontré et réaffecté à "ceci est une variable"*/
alert(func); // ceci est une variable
</script>
Copiez le code comme suit :
<script type="text/javascript">
var nom = "feng"; fonction func()
{
/*Tout d'abord, attribuez name à undefined dans l'environnement func, puis recherchez l'attribut name de l'objet actif dans l'environnement func pendant l'exécution. À ce stade, la valeur a été précompilée sur undefined, donc la sortie est indéfinie, pas. feng */
alert(name); //nom de variable non défini = "JSF";
alerte(nom); //JSF
}
fonction();
alerte(nom);
//feng
</script>
Bien que les déclarations de variables et de fonctions puissent se trouver n'importe où dans le document, il est recommandé de déclarer les variables et fonctions globales avant tout le code JavaScript, ainsi que d'initialiser et d'affecter les variables. Dans une fonction, les variables sont d'abord déclarées puis référencées.
1.3 Exécuter le code JavaScript par blocs
Les blocs de code sont des segments de code séparés par des balises <script>. Par exemple, les deux balises <script> ci-dessous représentent deux blocs de code JavaScript.
Copiez le code comme suit :
<script>
// Bloc de code JavaScript 1
var a = 1 ;
</script>
<script>
// Bloc de code JavaScript 2
fonction f(){
alerte(1);
}
</script>
Lorsque l'interpréteur JavaScript exécute un script, il l'exécute par blocs. En termes simples, si le navigateur rencontre une balise <script> lors de l'analyse du flux de document HTML, l'interpréteur JavaScript attendra que le bloc de code soit chargé, précompilera d'abord le bloc de code, puis l'exécutera. Après l'exécution, le navigateur continue d'analyser le flux de document HTML ci-dessous et l'interpréteur JavaScript est prêt à traiter le bloc de code suivant.
Étant donné que JavaScript est exécuté par blocs, si vous appelez une variable ou une fonction déclarée dans un bloc suivant dans un bloc JavaScript, une erreur de syntaxe sera générée. Par exemple, lorsque l'interpréteur JavaScript exécute le code suivant, il génère une erreur de syntaxe, indiquant que la variable a n'est pas définie et que l'objet f est introuvable.
Copiez le code comme suit :
<script>
// Bloc de code JavaScript 1
alerte(a);
f();
</script>
<script>
// Bloc de code JavaScript 2
var a = 1 ;
fonction f(){
alerte(1);
}
</script>
Bien que JavaScript soit exécuté par blocs, différents blocs appartiennent à la même portée globale, ce qui signifie que les variables et les fonctions entre blocs peuvent être partagées.
1.4 Utiliser le mécanisme d'événement pour modifier l'ordre d'exécution de JavaScript
Étant donné que JavaScript traite le code par morceaux et suit l'ordre d'analyse du flux de documents HTML, vous verrez de telles erreurs de syntaxe dans l'exemple ci-dessus. Mais lorsque le flux de documents est chargé, une telle erreur ne se produira pas si vous y accédez à nouveau. Par exemple, si le code qui accède aux variables et fonctions dans le deuxième bloc de code est placé dans la fonction d'événement d'initialisation de la page, il n'y aura aucune erreur de syntaxe.
Copiez le code comme suit :
<script>
// Bloc de code JavaScript 1
window.onload = function(){ // Fonction de gestion des événements d'initialisation de page
alerte(a);
f();
}
</script>
<script>
// Bloc de code JavaScript 2
var a = 1 ;
fonction f(){
alerte(1);
}
</script>
Pour des raisons de sécurité, nous n'autorisons généralement l'exécution de code JavaScript qu'après l'initialisation de la page. Cela peut éviter l'impact de la vitesse du réseau sur l'exécution de JavaScript, ainsi que les restrictions sur l'exécution de JavaScript causées par le flux de documents HTML.
Avis
S'il existe plusieurs gestionnaires d'événements windows.onload dans une page, seul le dernier est valide. Pour résoudre ce problème, vous pouvez placer tous les scripts ou fonctions appelantes dans le même gestionnaire d'événements onload, par exemple :
Copiez le code comme suit :
window.onload = fonction(){
f1();
f2();
f3();
}
Et de cette manière, l'ordre d'exécution des fonctions peut être modifié en ajustant simplement l'ordre d'appel des fonctions dans le gestionnaire d'événements onload.
En plus des événements d'initialisation de page, nous pouvons également modifier l'ordre d'exécution du code JavaScript via divers événements interactifs, tels que les événements de souris, les événements de clavier, les déclencheurs d'horloge, etc. Pour une explication détaillée, veuillez vous référer au chapitre 14.
1.5 Ordre d'exécution des scripts de sortie JavaScript
Dans le développement JavaScript, la méthode write() de l'objet document est souvent utilisée pour générer des scripts JavaScript. Alors, comment ces scripts de sortie dynamique sont-ils exécutés ? Par exemple:
Copiez le code comme suit :
document.write('<script type="text/javascript">');
document.write('f();');
document.write('function f(){');
document.write('alert(1);');
document.write('}');
document.write('</script>');
En exécutant le code ci-dessus, nous constaterons que : la méthode document.write() écrit d'abord la chaîne de script de sortie à l'emplacement du document où se trouve le script. Après avoir analysé le contenu du document où se trouve document.write(), le code ci-dessus apparaît. Le navigateur continue d'analyser le contenu de sortie de document.write (), puis d'analyser les documents HTML suivants dans l'ordre. En d'autres termes, la chaîne de code générée par le script JavaScript sera exécutée immédiatement après la sortie.
Veuillez noter que la chaîne de script JavaScript sortie à l'aide de la méthode document.write() doit être placée dans la balise <script> qui est sortie en même temps, sinon l'interpréteur JavaScript ne sera pas en mesure de reconnaître ces codes JavaScript légaux et le fera. être affiché sous forme de chaîne ordinaire dans le document de page. Par exemple, le code suivant affichera le code JavaScript au lieu de l'exécuter.
Copiez le code comme suit :
document.write('f();');
document.write('function f(){');
document.write('alert(1);');
document.write(');');
Cependant, il existe certains risques liés à la sortie et à l'exécution de scripts via la méthode document.write(), car différents moteurs JavaScript les exécutent dans des ordres différents et des bogues peuvent survenir dans différents navigateurs lors de l'analyse.
Ø Problème 1 : Les variables ou fonctions déclarées dans le fichier JavaScript externe importé via la méthode document.write() sont introuvables. Par exemple, regardez l’exemple de code ci-dessous.
Copiez le code comme suit :
document.write('<script type="text/javascript" src="//www.VeVB.COm/test.js">
</script>');
document.write('<script type="text/javascript">');
document.write('alert(n);'); // IE indique que la variable n est introuvable
document.write('</script>');
alert(n+1); // Tous les navigateurs indiqueront que la variable n est introuvable
Le code du fichier JavaScript externe (test.js) est le suivant :
Copiez le code comme suit :
variable n = 1 ;
Lors du test dans différents navigateurs, vous trouverez une erreur de syntaxe et la variable n est introuvable. Autrement dit, si vous accédez dans un bloc de code JavaScript aux variables contenues dans le fichier JavaScript externe importé dans la sortie du script par la méthode document.write() dans ce bloc de code, une erreur de syntaxe sera affichée. En même temps, si dans le navigateur IE, non seulement dans le script, mais également dans le script de sortie, il sera demandé que la variable de sortie importée dans le fichier JavaScript externe soit introuvable (l'expression est un peu longue et alambiquée, les lecteurs qui ne comprennent pas peuvent essayer d'exécuter le code ci-dessus peuvent être compris).
Ø Question 2 : Différents moteurs JavaScript ont des ordres d'exécution légèrement différents pour les scripts d'importation externes de sortie. Par exemple, regardez l’exemple de code ci-dessous.
Copiez le code comme suit :
<script type="text/javascript">
document.write('<script type="text/javascript" src="http://shaozhuqing.com/test1.js">
</script>');
document.write('<script type="text/javascript">');
document.write('alert(2);')
document.write('alert(n+2);');
document.write('</script>');
</script>
<script type="text/javascript">
alerte(n+3);
</script>
Le code du fichier JavaScript externe (test1.js) est présenté ci-dessous.
Copiez le code comme suit :
variable n = 1 ;
alerte(n);
La séquence d'exécution dans le navigateur IE est illustrée à la figure 1-6.
Figure 1-6 La séquence d'exécution et les erreurs de syntaxe signalées par le navigateur IE 7
L'ordre d'exécution dans les navigateurs conformes aux normes DOM est différent de celui des navigateurs IE, et il n'y a aucune erreur de syntaxe. La figure 1-7 montre l'ordre d'exécution dans le navigateur Firefox 3.0.
Figure 1-7 Séquence d'exécution du navigateur Firefox 3 et erreurs de syntaxe affichées
Résolvez les différents ordres d’exécution des différents navigateurs et les éventuels bugs. Nous pouvons placer tous les fichiers externes importés à l'aide du script de sortie dans des blocs de code indépendants, afin que ce problème puisse être évité selon l'ordre d'exécution des blocs de code JavaScript introduit ci-dessus. Par exemple, pour l’exemple ci-dessus, vous pouvez le concevoir comme ceci :
Copiez le code comme suit :
<script type="text/javascript">
document.write('<script type="text/javascript" src="//www.VeVB.COm/test1.js"></script>');
</script>
<script type="text/javascript">
document.write('<script type="text/javascript">');
document.write('alert(2);') ; // Astuce 2
document.write('alert(n+2);'); // Astuce 3
document.write('</script>');
alerte(n+3); // Astuce 4
</script>
<script type="text/javascript">
alert(n+4); // Astuce 5
</script>
De cette façon, le code ci-dessus peut être exécuté dans l'ordre dans différents navigateurs et l'ordre de sortie est 1, 2, 3, 4 et 5. La raison du problème est la suivante : une contradiction entre le script importé en sortie et le bloc de code JavaScript actuel. Si la sortie est séparée, il n'y aura pas de conflit.