IV. Les instructions▲
Mis à part lorsqu'elles contiennent des opérateurs induisant des effets de bord (en particulier, les opérateurs d'affectation et d'incrémentation), les expressions qui ont été présentées au précédent chapitre se contentent de produire une valeur, mais n'ont aucun rôle actif dans l'exécution d'un programme. L'exécution proprement dite est réalisée grâce au répertoire d'instructions dont dispose le langage. L'objet de ce nouveau chapitre est d'introduire les diverses instructions utilisables sous JavaScript. Mais avant tout, il convient de préciser que JavaScript dispose aussi de deux types d'instructions :
- les instructions simples qui se résument à des instructions atomiques comme les instructions expression (s+=12; ou index--; ou encore Res=(index > 3) ? "OK" :'KO';)… de même que les appels de fonctions (prompt('Voulez-vous un cafe ?'); )
- les instructions composées qui constituent donc un bloc composé de plusieurs instructions et bordé par deux accolades {…}.
IV-A. Les tests▲
Les instructions de test disponibles en JavaScript sont celles que l'on connaît pour beaucoup d'autres langages. Il s'agit de l'instruction if et de l'instruction if…else. La syntaxe de l'instruction if est la suivante :
if
(<
expression booléenne>
) <
instruction>
Son fonctionnement est le même que pour les autres langages : si le résultat de l'évaluation de l'expression est true ou peut être converti vers true, alors l'instruction est exécutée ; si le résultat de l'évaluation de l'expression est false ou peut être converti vers false, alors l'instruction n'est pas exécutée. Il convient de noter dans la syntaxe, l'obligation d'encadrer l'expression booléenne entre deux parenthèses. Par ailleurs, il est bien évident que l'instruction conditionnelle peut être simple ou composée.
La seconde forme de l'instruction est donc le if…else dont la syntaxe est la suivante :
if
(<
expression booléenne>
) <
instruction 1
>
;
else
<
instruction 2
>
Son exécution, s'il est besoin de le préciser, est le suivant : si le résultat de l'évaluation de l'expression est true ou peut être converti en true, alors l'instruction 1 est exécutée ; si le résultat de l'évaluation de l'expression est false ou peut être converti vers false, alors c'est l'instruction 2 qui 'est exécutée. Les remarques concernant l'instruction if s'appliquent à l'instruction if…else. De plus, on remarquera dans la syntaxe le point-virgule précédant else. Cela ne sera pas sans surprendre ceux qui connaissent le langage Pascal où justement ce caractère placé à cet endroit était totalement en défaut par rapport à la syntaxe.
Pour être précis, ce caractère « ; » n'est absolument nécessaire que dans le cas d'une écriture linéaire d'une telle instruction. En effet, en JavaScript, le retour à la ligne vaut le « ; » (sauf quand l'instruction n'est pas syntaxiquement finie). Ainsi, une écriture du style : Sélectionnez
est tout à fait correcte et admise par la syntaxe. Le retour à la ligne après l'expression booléenne appelle une suite constituée par l'instruction 1. Par contre, après celle-ci, l'instruction if est syntaxiquement achevée et donc, le retour à la ligne vaut le « ; » nécessaire à cet endroit. Conséquence de ce qui vient d'être dit : même si le else est, comme ici, suivi d'un retour à la ligne, l'instruction placée à la ligne suivante fera partie intégrante de l'instruction else. Si l'on veut que l'instruction qui lui est associée soit une instruction vide (ce qui peut sembler bizarre, car on peut alors se poser la question de l'utilité du else), il faudra prévoir effectivement un « ; » à la suite. |
Les instructions if peuvent être enchâssées. Dans ce cas, si l'une ou plusieurs d'entre elles sont complétées d'instructions else, il apparaît souhaitable de connaître très précisément la syntaxe afin d'éviter toute erreur d'interprétation dans l'évaluation. Considérons, par exemple, l'écriture suivante :
V1 =
V2 =
12
;
V3 =
16
;
if
(V1 >=
V2)
if
(V2 >=
V3)
alert
(V3 +
'
n\'est
pas
strictement
superieur
a
'
+
V1)
else
alert
(V1 +
'
est
strictement
inferieur
a
'
+
V2)
Exec
Étudiez ce programme. A priori il semble cohérent avec le contenu des fenêtres alert qui sont prévues !… Et pourtant !… Essayez de l'exécuter.
L'indentation qui a été choisie représentait ce que l'utilisateur voulait signifier. En ce sens, effectivement, tout semble correct. Le problème vient du fait que le else se réfère au if le plus proche. Un moyen simple de se rappeler cela consiste à dire que if est à else ce que la parenthèse gauche est à la parenthèse droite, dans une expression correctement parenthésée, bien sûr ! Et là apparaît peut-être l'intérêt d'une instruction vide après un else… Il est néanmoins préférable d'utiliser la structure de bloc, ce qui donne :
V1 =
V2 =
12
;
V3 =
16
;
if
(V1 >=
V2){
if
(V2 >=
V3)
alert
(V3 +
'
n\'est
pas
strictement
superieur
a
'
+
V1)}
else
alert
(V1 +
'
est
strictement
inferieur
a
'
+
V2)
IV-B. Les boucles▲
JavaScript, comme la plupart des langages de programmation, comporte deux types de boucle : les boucles non bornées et les boucles bornées.
Les premières sont celles dont on ne connaît pas le nombre de fois qu'elles seront exécuté, car le test de fin de boucle est une expression booléenne mettant en jeu des informations non connues, même de façon formelle, au moment de l'écriture du programme.
Les autres sont celles pour lesquelles, au moment de la rédaction du programme, on sait (au moins de façon formelle) combien de fois elles doivent boucler (boucles muettes où la valeur de l'indice de boucle peut n'avoir aucun rôle dans les instructions qui en font partie) ou à quelle valeur on doit commencer le calcul, à quelle valeur il se termine et quel est le pas de variation entre chaque itération (boucles expressives où la valeur d'indice a une fonction dans les calculs).
La première instruction de boucle non bornée est l'instruction while dont la syntaxe est la suivante :
while
(<
expression booléenne>
)
<
corps de boucle>
Le corps de boucle peut se réduire à une seule instruction ou, au contraire, en comporter plusieurs. Dans ce cas, bien sûr, le bloc sera délimité par { et }. Comme pour les autres langages que vous connaissez peut-être, le fonctionnement de la boucle while est le suivant :
- Évaluation de l'expression booléenne d'entrée ;
- Si cette évaluation délivre la valeur false, la boucle est terminée et l'exécution se poursuit en séquence vers 4.
Si le résultat de l'évaluation est true, le corps de boucle est exécuté ; - Retour en 1 ;
- Suite du programme.
En conséquence, une boucle while peut ne pas être exécutée dans le cas où le test d'entrée se révèle toujours faux. A contrario et comme dans tous les autres langages, la logique de programmation réclame que si l'entrée dans la boucle est possible, l'environnement servant à l'évaluation de l'expression booléenne subisse une modification dans le corps de boucle, faute de quoi le programme sera dans une boucle infinie.
La seconde instruction de boucle non bornée est le do/while qui, pour les habitués de Pascal, correspond, d'un point de vue logique, au repeat/until. Sa syntaxe est la suivante :
do
<
corps de boucle>
while
(<
expression booléenne>
);
Par rapport à l'instruction précédente, il est évident de constater que cette boucle s'exécute au moins une fois et ce n'est qu'après cette exécution qu'est évaluée l'expression booléenne afin de déterminer si la boucle doit être à nouveau exécutée ou pas. Par rapport au repeat/until de Pascal, on notera toutefois l'inversion du test puisqu'ici la boucle se maintient tant que l'expression à une valeur true alors qu'en Pascal le processus se réitère tant que l'expression a une valeur false.
La boucle bornée est la boucle for dont la syntaxe est décrite ci-dessous :
for
([
var
]
<
ident>=
<
init>
;
<
test de fin>
;
<
opération>
)
<
corps de boucle>
Le fait de faire précéder l'identificateur d'index de boucle du mot réservé var est optionnel. Pour plus de détails, revenir au § I.1Qu'est-ce-que-JavaScript-?. La commande for se compose donc de trois composants séparés par le caractère « ; ». En premier lieu, on trouve l'affectation de la variable index de boucle à sa valeur initiale. Ensuite se situe une expression booléenne évaluée avant d'entrer dans le corps et constituant un test d'arrêt (effectif si son évaluation délivre la valeur false). Enfin, le troisième élément est une action effectuée au sortir du corps de boucle et permettant, en règle générale, d'effectuer l'incrémentation de l'index. Comme précédemment, le corps de boucle peut soit se réduire à une seule instruction, soit, s'il en comporte plusieurs, nécessiter leur encadrement par { et } pour définir une structure de bloc.
Voici donc un exemple simple d'une telle boucle dont vous pouvez obtenir le résultat de l'exécution :
var
S =
"
"
;
for
(var
I =
0
;
I <
10
;
I+
+
)
S +
=
I;
alert
("
La
boucle
a
construit
la
chaine
:
"
+
S);
Exec
Mais au-delà d'une telle utilisation « canonique », on peut imaginer d'autres formes d'utilisations de la boucle for. Voici un exemple qui va nous permettre de montrer à la fois comment le pas d'incrémentation peut être quelconque (et en tout cas différent de 1) et comment décrire un while avec un for (on avait plutôt l'habitude inverse). Voici l'exécution.
var
arret =
true
,
S =
"
"
,
Add =
'
abc
'
;
alert
("
Je
demarre
"
);
for
(var
i =
1
;
arret ;
i +
=
3
){
alert
("
Dans
for,
i
=
"
+
i);
S +
=
Add
arret =
!
(S.
length >
8
);
}
alert
("
J'en
suis
sorti
!!!
"
)
Exec
On voit que l'incrément (ici, 3) a pu être pris en compte grâce à l'opérateur +=. Quant au test d'arrêt, on voit qu'il peut n'avoir aucun lien direct avec l'index. C'est en fait une expression booléenne quelconque qui, d'une part est évaluée avant l'entrée dans le corps de boucle, et, d'autre part, évaluée à false provoque l'abandon de la boucle… EXACTEMENT COMME POUR LE while !!!
Grâce aux opérateurs de pré ou postincrémentation, dans le cas d'un pas de 1, l'incrémentation peut être réalisée dans le test, laissant ainsi le troisième argument libre pour réaliser une opération quelconque. Reprenons l'avant-dernier exemple… On peut le modifier comme suit et vérifier que l'exécution reste inchangée modulo une translation compréhensible des valeurs de début et fin.
Var S =
"
"
;
for
(var
I =
-
1
;
I+
+
<
9
;
S +
=
I)
alert
("
La
boucle
a
construit
la
chaine
:
"
+
S);
Exec
En intégrant la postincrémentation dans le troisième champ de l'instruction, les valeurs de début et fin restaient inchangées… la preuve !
var
S =
"
"
;
for
(var
I =
0
;
I <
10
;
S +
=
I+
+
);
alert
("
La
boucle
a
construit
la
chaine
:
"
+
S);
Exec
Enfin, il convient de noter que l'opérateur « , » permet de multiplier le nombre de variables, de tests et/ou d'opérations dans une boucle for. Il ne faut pas confondre cette structure avec des boucles enchâssées‚ où chacune gère une variable. Ici toutes les variables progressent simultanément. Voici un exemple qui va nous servir à illustrer cela :
var
S =
"
"
;
for
(var
I =
1
;
I <
6
;
I+
+
)
for
(var
J =
2
;
J <
7
;
J +
=
2
)
for
(var
K =
3
;
K <
8
;
K +
=
3
)
S +
=
"
"
+
I +
J +
K;
alert
("
Chaine
construite
:
"
+
S);
var
S =
"
"
;
for
(var
I=
1
,
J=
2
,
K=
3
;
I<
6
,
J<
7
,
K<
8
;
I+
+
,
J+
=
2
,
K+
=
3
)
S +
=
"
"
+
I +
J +
K;
alert
("
Chaine
construite
:
"
+
S);
Le résultat des boucles enchâssées correspond bien à ce à que l'on attendait. I étant initialisé à 1, J l'est à 2 tandis que K va balayer toutes les valeurs de 3 à 7 par pas de 3 (soit 3 et 6) avant que J ne passe à 4, etc. Pour la boucle multiple, les trois tests sont évalués avant l'exécution du corps ; dès que l'un d'eux est évalué à false, la boucle est stoppée. Ici, la première boucle sera effectuée pour I=1, J=2, K=3, la seconde pour I=2, J=4, K=6, mais la troisième ne sera pas exécuté, car bien que I (qui prend la valeur 3) et J (qui prend la valeur 6), soient bien dans les bornes autorisées, K qui vaut à présent 9 met en défaut K<8.
La boucle for revêt une autre forme adaptée à la structure objet. Sa syntaxe est alors la suivante :
for
([
var
]
<
ident>
in
<
objet>
)
<
corps de boucle>
La variable va énumérer tous les noms de propriétés associées à l'objet référencé. Nous avons utilisé de nombreuses fois ce type de boucle lorsque nous avons abordé les objets au § II.7Les-Objets. Nous allons en donner ici un rapide exemple qui va nous permettre d'énumérer toutes les propriétés/méthodes contenues dans cette fenêtre.
Var S =
"
Proprietes
de
window
:\n
"
;
for
(var
i in
this
) //
ou
window
S +
=
i +
"
,
"
;
alert
(S);
Exec
On note au passage que i prend pour valeurs successives la chaîne désignant le nom de la propriété et non la valeur. Nous verrons dans le prochain chapitre traitant des objets que pour obtenir la valeur effective il faudra utiliser l'accès associatif à l'objet… à l'exception du cas de l'objet window !!!
On notera aussi que les propriétés énumérées contiennent celles introduites par le constructeur window, mais aussi celles qui ont été rajoutées ensuite (fonctions définies dans cette page, images, etc.).
IV-C. Les ruptures▲
Les ruptures de séquences constituent un concept qui fut largement (trop peut-être) utilisé dans les langages de programmation d'ancienne génération (Fortran, Basic, Cobol, etc.) Ensuite sont apparus des langages de programmation structurée tournant résolument le dos à cette notion (Algol W, Pascal…). Les langages récents (C, Java, JavaScript, Perl) réintroduisent les ruptures de séquences utilisant, dans certains cas, des étiquettes pour effectuer des sorties de blocs (boucles, fonctions, aiguillages).
La syntaxe des étiquettes suit celle des identificateurs de JavaScript (voir § II.1Les-identificateurs). La syntaxe est particulièrement simple. Il suffit de faire précéder l'instruction que l'on désire étiqueter par une étiquette suivie de « : ».
<
ident étiquette>
:
<
instruction>
Nous avons déjà introduit auparavant des étiquettes particulières. En effet case et default apparaissant dans une instruction switch ont un statut d'étiquettes. Bien que syntaxiquement on puisse étiqueter n'importe quelle instruction, dans les faits, seules les boucles que nous venons d'étudier seront concernées afin d'effectuer, soit des abandons définitifs (break) soit des abandons de l'itération en cours et passage à l'éventuelle itération suivante (continue).
goto est un mot réservé de JavaScript, mais l'instruction correspondante n'est pas reconnue du langage.
L'instruction break provoque la sortie immédiate d'une instruction d'aiguillage (switch) ou de la boucle dans laquelle elle apparaît (pas au-delà dans le cas de boucles imbriquées). Hors de ces contextes, l'occurrence de l'instruction break (seule) provoque une erreur.
Si l'instruction break comporte une étiquette, celle-ci doit impérativement désigner une instruction d'un niveau supérieur à celui où apparaît l'appel. Dans ce cas, c'est tout le bloc ainsi désigné qui sera abandonné. À noter que contrairement au cas précédent, le break étiqueté peut être employé dans n'importe quel contexte définissant de façon implicite ou explicite un bloc. On peut ainsi nommer, par exemple, une instruction if ou de façon plus générale une suite quelconque d'instructions encadrées d'accolades même si celles-ci sont mises dans le seul but de nommer la suite d'instructions qu'elles contiennent.
Voici un exemple mettant en jeu ce qui vient d'être expliqué. Essayez de déterminer ce que va être la sortie puis vérifiez.
L'instruction break provoque la sortie immédiate d'une instruction d'aiguillage (switch) ou de la boucle dans laquelle elle apparaît (pas au-delà dans le cas de boucles imbriquées). Hors de ces contextes, l'occurrence de l'instruction break (seule) provoque une erreur.
Si l'instruction break comporte une étiquette, celle-ci doit impérativement désigner une instruction d'un niveau supérieur à celui où apparaît l'appel. Dans ce cas, c'est tout le bloc ainsi désigné qui sera abandonné. À noter que contrairement au cas précédent, le break étiqueté peut être employé dans n'importe quel contexte définissant de façon implicite ou explicite un bloc. On peut ainsi nommer, par exemple, une instruction if ou de façon plus générale une suite quelconque d'instructions encadrées d'accolades même si celles-ci sont mises dans le seul but de nommer la suite d'instructions qu'elles contiennent.
Voici un exemple mettant en jeu ce qui vient d'être expliqué. Essayez de déterminer ce que va être la sortie puis vérifiez.
var
S =
"
Valeurs
successives
d'index
:\n
"
;
Boucle1
:for
(var
i =
0
;
i <
5
;
i+
+
){
Boucle2:
for
(var
j =
0
;
j <
6
;
j+
=
2
){
if
(j >
2
) break
;
if
(i =
=
1
) break
Boucle2;
if
(i =
=
4
) break
Boucle1;
S +
=
"
i
=
"
+
i +
"
j
=
"
+
j +
"
\n
"
;
}
}
S +
=
"
En
sortie
:
i
=
"
+
i +
"
j
=
"
+
j +
"
\n
"
;
alert
(S);
Exec
L'instruction continue comme break, interrompt la boucle en cours. Mais, alors que break termine définitivement la boucle, continue se contente d'abandonner l'itération en cours pour passer directement à celle qui suit. Cela impose donc, dans une boucle while ou do/while, que l'environnement servant à évaluer l'expression gérant la fin de boucle ait été réactualisé avant l'exécution de l'instruction continue, faute de quoi on sera en présence d'une boule infinie. Cette précaution est sans objet dans une boucle for puisqu'après une instruction continue, l'exécution se poursuit vers l'incrémentation, dans un premier temps, avant de procéder au test.
Dans Navigator 4, la condition du do/while n'est plus évaluée après l'exécution de l'instruction continue, si bien que l'itération suivante est lancée systématiquement !
L'instruction continue peut donc apparaître dans le corps d'une boucle while ou for ou encore for/in (l'utilisation dans un do/while étant fortement déconseillée). Hors de ces contextes, l'occurrence de l'instruction continue provoque une erreur de syntaxe.
Tout comme l'instruction break , continue peut être associée à une étiquette, celle-ci devant impérativement désigner une instruction d'un niveau supérieur à celui où apparaît l'appel. Dans ce cas, c'est au niveau de l'itération suivante de la boucle ainsi désignée que se poursuivra l'exécution.
Voici un exemple mettant en jeu ce qui vient d'être expliqué. Essayez de déterminer ce que va être la sortie puis vérifiez.
Var S =
"
Valeurs
successives
d'index
:\n
"
;
Boucle:
for
(var
i =
0
;
i <
4
;
i+
+
){
for
(var
j =
0
;
j <
5
;
j+
=
2
){
if
(j =
=
2
) continue
;
if
(i =
=
1
) continue
Boucle;
S +
=
"
i
=
"
+
i +
"
j
=
"
+
j +
"
\n
"
;
}
}
S +
=
"
En
sortie
:
i
=
"
+
i +
"
j
=
"
+
j +
"
\n
"
;
alert
(S);
Exec
IV-D. Préfixage d'objets▲
L'écriture induite par un langage objet peut devenir lourde lorsqu'on désire, faire référence à une propriété définie à un niveau très profond dans la hiérarchie des objets. Par exemple, si on définit dans le document contenu dans cette fenêtre, un formulaire contenant un champ de texte dont la valeur est « Le lien … » et que nous voulons remplacer cette chaîne par le nom du lien qui va lui-même permettre de réaliser cette opération, il faudra exécuter l'instruction suivante :
window.
document.
Formul.
textfield.
value =
window.
document.
links[
14
]
;
Vous pouvez contrôler cela en observant la barre de statut au bas de votre fenêtre alors que la souris survole le bouton de déclenchement…
…où ChgTxt est une fonction JavaScript se résumant à l'instruction ci-dessus. (Pourquoi 14 ?… Parce que je sais que c'est le quinzième de cette page et que les indices de tableau débutent en 0, tout simplement !!!)
En fait, pour les curieux qui vont vérifier le source, ils verront que pour le site « Developpez.com » qui rajoute des liens dont je n'ai pas la maitrise, j'ai opéré d'une autre manière.
L'exemple que nous venons de prendre, bien qu'il ne soit pas particulièrement compliqué, va nous permettre, néanmoins, de montrer l'utilité et le fonctionnement de l'instruction with. Encore une fois, la syntaxe de cette instruction est particulièrement simple :
with
(<
objet>
)
<
corps de with
>
Comme d'habitude, le corps de cette instruction peut se limiter à une seule instruction ou peut en contenir plusieurs, auquel cas, elles seront encadrées par { et }. L'utilité de cette instruction est de définir temporairement un objet standard tel que toutes les références de propriétés de celui-ci apparaissant dans le corps peuvent être résolues sans qu'il soit besoin dudit objet. Ainsi, dans notre exemple précédent, nous aurions pu écrire :
with
(window.
document)
Formul.
textfield.
value =
links[
14
]
;
L'intérêt est ici modeste, mais dans le cas où le corps de l'instruction contient un nombre non négligeable de références à l'objet mis en préfixe, on comprend que cela puisse devenir intéressant. Il est évident que dans le corps d'un with, pourront apparaître (et cela est heureux !…) des variables n'ayant aucun lien avec l'objet standard (indices de boucles ou autres). On en déduit donc que le préfixage n'interviendra que lorsqu'il sera fait référence à une propriété existante de cet objet.
Au risque d'anticiper sur le prochain chapitre traitant spécifiquement des objets, supposons que pour un objet que nous appellerons « Ordinateur » on ait déjà défini les propriétés « Systeme », « Memoire » et « Disque », et que l'on veuille leur affecter une valeur et rajouter une nouvelle propriété : « Processeur ». Considérons les deux portions de programme suivantes :
with
(Ordinateur){
S =
"
Proprietes
de
Ordinateur
:\n
"
;
Systeme =
"
WinXP
"
;
Memoire =
1024
;
Disque =
80000
;
Processeur =
"
Pentium
IV
"
;
}
for
(var
i in
Ordinateur)
S +
=
i +
"
=
"
+
Ordinateur[
i]
+
"
,\n
"
;
alert
(S);
with
(Ordinateur){
S =
"
Proprietes
de
Ordinateur
:\n
"
;
Systeme =
"
WinXP
"
;
Memoire =
1024
;
Disque =
80000
;
Ordinateur.
Processeur =
"
Pentium
IV
"
;
}
for
(var
i in
Ordinateur)
S +
=
i +
"
=
"
+
Ordinateur[
i]
+
"
,\n
"
;
alert
(S);
On constate que dans le premier cas, la liste des propriétés ne contient pas « Processeur ». En fait, on a simplement défini non pas une propriété de l'objet « Ordinateur », mais une variable de type chaîne à laquelle on a affecté la valeur « Pentium IV ». De la même manière que S, par exemple n'est pas, non plus, une propriété de ce même objet. Dans le second cas, par contre, on a spécifié, bien qu'étant dans le corps du with, Ordinateur.Processeur = « Pentium IV ». On vérifie que la propriété a alors bien été rajoutée à l'objet.
IV-E. Les définitions de fonctions▲
L'instruction function de JavaScript permet de définir un objet fonction en tant que propriété/méthode de l'objet dans lequel il est défini. Sa syntaxe est la suivante :
function
<
ident>
([
<
par1>
[
,
<
par2>
[
.
.
.
,
<
parp>
]
.
.
.
]
){
<
corps de function
>
}
Dans cette syntaxe, il apparaît que les parenthèses sont obligatoires (même s'il n'y a pas de paramètres), de même que les accolades (même si le corps se réduit à une seule instruction) à la différence de ce que nous avons vu précédemment pour les corps de boucle.
Le fait de classer la définition des fonctions dans les instructions se place sur le même plan que ce que nous verrons dans le prochain paragraphe : ajout d'une propriété d'un objet contenant ; mais, comme dans les autres langages, la définition n'engendre pas l'exécution. Vous pouvez même, si le cœur vous en dit, définir une fonction dont les instructions ne seront jamais exécutées. En fait, au chargement de la page, le code JavaScript est analysé, puis ce qui est au niveau global est effectivement exécuté (c'est ce qui a été appelé au § I.5Comment-JavaScript-est-il-invoqué-? fonctionnement synchrone). L'exécution d'une fonction, et donc des instructions qu'elle contient, ne se fera que de façon asynchrone par appel de ladite fonction. Cela va avoir des répercussions surprenantes (dont il faudra tenir compte) sur l'exécution. Considérons par exemple un document contenant le script suivant :
<
script language=
"
JavaScript
"
>
alert
(Succ
(6
));
//
Appel
de
la
fonction
alert
(Succ);
//
Affich
de
la
fonction
Succ =
0
;
function
Succ
(x) {
//
Définition
return
x+
1
;
}
alert
(Succ);
//
Affich
de
la
fonction
?
<
/
script>
Exec
Le fait de cliquer sur le bouton Exec a provoqué l'ouverture d'une page (vous l'avez peut-être aperçue au centre de l'écran). La fonction Succ est donc une propriété de cette page (analyse au chargement) qui va être utilisée puis modifiée par le script.
IV-F. Les déclarations▲
Bien que nous ayons commencé ce cours par un paragraphe introduisant la notion de variable JavaScript, nous ne pouvions pas éviter d'en reparler dans ce chapitre, car la déclaration explicite d'une variable est effectivement une instruction qui peut, comme on l'a vu, apparaître n'importe où dans un script. On peut toutefois compléter ce qui a donc été dit au § I.1Qu'est-ce-que-JavaScript-? en précisant que l'opérateur « , » va trouver un de ses emplois les plus fréquents dans ce type d'instruction. En effet, la syntaxe générale est de la forme :
var
<
ident1>
[
=
<
valeur1]
[
,
.
.
.
.
.
,
<
identp>
[
=
<
valeurp>
]
.
.
.
.
]
Avant d'en terminer, il convient de préciser que le fait de définir une variable va avoir pour effet de la rajouter en tant que propriété de l'objet qui la contient. Si c'est au niveau global qu'elle est définie, ce sera une propriété de l'objet window, si c'est dans une fonction, ce sera une propriété de cet objet fonction, lui-même objet de window (si la fonction est définie au niveau global)…
La latitude de déclarer ou pas de façon explicite des variables peut avoir des conséquences éventuellement fâcheuses sur l'exécution d'un programme. En effet, une déclaration implicite, même si elle est opérée à l'intérieur d'une fonction, se traduit par une déclaration au niveau le plus haut. Si à ce niveau, une variable de même nom existe, elle sera substituée à la nouvelle variable implicitement déclarée et sa valeur sera donc affectée par les modifications survenues au niveau inférieur. Pour bien comprendre cela, regardons les résultats obtenus par ces deux programmes où la seule différence réside dans la déclaration de la variable i dans la fonction effectuée soit de façon explicite, soit de façon implicite…
S=
"
"
;
for
(i=
1
;
i<
6
;
i+
+
)
enumerer
(i);
alert
(S);
function
enumerer
(x){
for
(var
i=
8
;
i<
12
;
i+
+
) //
decl.
explicite
S+
=
"
(
"
+
x+
"
,
"
+
i+
"
)
"
;
S+
=
"
\n
"
;
}
S=
"
"
;
for
(i=
1
;
i<
6
;
i+
+
)
enumerer
(i);
alert
(S);
function
enumerer
(x){
for
(i=
8
;
i<
12
;
i+
+
) //
decl.
implicite
S+
=
"
(
"
+
x+
"
,
"
+
i+
"
)
"
;
S+
=
"
\n
"
;
}