En tout premier lieu, en particulier pour ceux qui n'y
sont pas habitués, il est important de signaler que le langage est
sensible à la casse des caractères.
Ainsi, si un identificateur est défini sous la forme MonIdent,
il ne pourra être référencé que par cette écriture.
Tout référencement ne respectant pas la casse des caractères
composant un identificateur provoquera une erreur par JavaScript lors de
l'exécution.
Exemple
:
var MonIdent = 12;
var i = 3;
i = i * monIdent;
//
déclaration explicite, type numérique
// déclaration explicite, type numérique
// monIdent
non déclaré -> Erreur à l'exécution
Dans l'exemple ci-dessus, on a commis l'erreur, sans doute
involontaire d'utiliser monIdent au lieu de
MonIdent. Dans certains contextes bien particuliers,
cette contrainte de respect de casse est levée, mais il vaut mieux
prendre l'habitude de la respecter systématiquement. En particulier,
lorsque nous utiliserons des fonctions prédéfinies de JavaScript,
il faudra veiller à respecter cette contrainte faute de quoi on aura
droit à l'erreur "fonction non définie".
JavaScript ignore tout caractère
d'espacement (blanc, tabulation, retour à la ligne, etc.) apparaissant
entre les entités lexicales. Ainsi, pour des besoins de présentation
d'un programme (pour une meilleure lisibilité) vous pouvez sans aucun
problème insérer des blancs par exemple, de part et d'autre
d'opérateurs), indenter des portions constituant des blocs ou couper
une ligne trop longue. Par contre une entité lexicale ne peut en aucun
cas contenir un caractère d'espacement sous peine de la transformer
en deux entités lexicales et donc, vraisemblablement de voir apparaître
une erreur. Par exemple, vous ne pouvez pas définir un identificateur
comme étant Mon_Ident.
Les identificateurs servent
à nommer des variables, des fonctions ou encore des étiquettes
(JavaScript 1.2). La syntaxe d'un identificateur impose
en première place un caractère alphabétique (majuscule
ou minuscule) ou $ (dollar) ou _ (souligné).
Les caractères suivants peuvent être n'importe quelle combinaison
de ces mêmes caractères plus des chiffres.
Exemple
:
Mon_Ident
$id31
_entier
valeur
Attention
:
Évitez de commencer un identificateur par deux "soulignés"
(__) consécutifs car il peut y avoir conflit avec certaines fonctions
prédéfinies du langage
2
- Les littéraux
Les valeurs constantes affectées à des variables
ou intervenant dans des comparaisons à celles-ci sont appelés
des littéraux. Ceux-ci peuvent être
de type numérique (entiers ou réels),
de type chaînes de caractères
ou de type booléen. A ces différents
types de littéraux, il convient d'ajouter, en JavaScript, la constante
null qui permet de représenter une
valeur différente de toute autre signifiant ainsi qu'une variable
possédant cette valeur n'en contient pas d'autre. Elle n'a donc pas
été affectée.
Bien que la distinction soit subtile, il ne faut pas confondre null
et undefined. D'abord l'un correspond, nous
venons de le voir, à un littéral, ce qui n'est pas le cas
pour l'autre. undefined est une valeur qui
est retournée (en cas de demande d'écriture ou par appel de
la fonction typeof()) pour une variable définie
mais non affectée (d'où la confusion), ou non définie
ou pour une propriété non définie d'un objet (nous
reviendrons là-dessus).
Attention
: le littéral null n'est pas, comme en C ou C++ équivalent
à 0. Dans certains cas, il pourra être converti en 0, mais
ne lui sera jamais équivalent.
De façon générale, les littéraux
de type numérique sont en représentation décimale.
Le langage accepte néanmoins des littéraux entiers
en représentation octale ou hexadécimale.
Les premiers, dont les digits sont compris bien évidemment entre
0 et 7, ont pour caractéristique de débuter par le chiffre
"0". Les seconds débutent par les caractères "0x"
et ont pour digits n'importe quel chiffre entre 0 et 9 ainsi que les lettres
A, B, C, D, E ou F (majuscules ou minuscules).
Les réels peuvent avoir une représentation
en virgule fixe (du type 3.14159) ou en
virgule flottante (du type 0.314 E+1 ou encore .314 e+1). Dans tous
les cas, la marque décimale est le "."
et non la ",", quant au signe d'exponentiation, il peut être
indifféremment en majuscule ou minuscule.
Les chaînes sont encadrées par des quotes
simples ( ' ) ou doubles ( " ). Si à l'intérieur d'une
chaîne encadrée par un de ces caractères, ce même
caractère doit apparaître, il sera précédé
du caractère "antislash" ( \ ). Il existe bien d'autres
caractères subissant ce traitement. Nous en reparlerons lorsque nous
étudierons spécifiquement les chaînes de caractères
et les expressions régulières.
Les littéraux peuvent avoir des formes plus complexes
que pour les types primitifs que nous venons
de voir. C'est le cas des "initialisateurs" de tableaux ou d'objets.
Nous ne donnerons ici que deux exemples, sans rentrer dans les détails
que nous aborderons lorsque nous étudierons ces deux concepts.
Comme en C, C++, Java, Pascal, les
instructions se terminent généralement par le caractère
";" afin de matérialiser la fin de l'instruction.
Toutefois, en JavaSript, celle-ci est optionnelle pour chaque instruction
suivie d'une fin de ligne. Cela peut sembler être un avantage,
mais peut aussi représenter un piège en fonction de
ce qui a été dit plus haut. En effet, il a été
dit que l'on peut, pour des raisons de lisibilité, introduire
des retours à la ligne dans des instructions très longues.
Dans ce cas, il faut veiller à deux choses :
La coupure ne peut avoir lieu à l'intérieur d'une unité
lexicale ; il est hors de question de couper en deux des identificateurs,
des chaînes de caractères ou des littéraux : cela va
irrémédiablement entraîner des erreur d'analyse (identificateur
non déclaré, chaîne non terminée) ou d'exécution.
Certaines instructions de rupture de séquence peuvent être
assorties ou non d'un identificateur. Elles sont particulièrement
sensibles au problème et leur mauvaise interprétation peut
avoir des conséquences fâcheuses sur la logique ou l'exécution
du programme. C'est le cas des instructions return
ou break que nous verrons plus loin
Exemple
:
var MonIdent = 12
var i = 3
2 * MonIdent/2
var j = 8
1 * Mon
Ident
var Nom = "Alain Terieur
"
//Instruction
bien analysée
// L'identificateur i est affecté à 3 (partie du littéral
32...)
// Curieusement cette ligne ne provoque pas d'erreur (elle
semble ignorée... Il n'en est rien)
// L'identificateur j est affecté à 8 (partie du littéral
81...)
//Erreur : identificateur Mon non défini !!!!... et
c'est tout !!!! //Erreur
: identificateur Ident non défini !!!!
//Erreur : chaîne de caractères non terminée.
De façon générale, il vaut mieux utiliser le point
virgule pour terminer les instructions. Cela rend le texte plus clair et
permet de visualiser très rapidement les risques d'erreur tels que
ceux qui viennent d'être signalés.
3
- Les Commentaires
On ne pouvait pas traiter ce chapitre sans parler de ce
que l'on a utilisé plusieurs fois jusqu'ici... les commentaires.
Les commentaires sont non seulement utiles, mais il vaudrait mieux dire
indispensables lorsqu'on programme. Il permettent d'indiquer la nature
du traitement effectué à tout endroit d'un programme, de préciser
une éventuelle astuce de programmation, de placer des pense-bête
afin de se souvenir qu'il convient de prévoir tel ou tel cas non
encore traité. Enfin et surtout, ils permettent de retrouver rapidement
la logique du programme lorsqu'on doit le modifier quelques mois, voire
quelques années après qu'on l'ait écrit.
En JavaScript on dispose de deux types de commentaires
: les commentaires ligne et les commentaires
multilingues. Les premiers portent principalement sur une instruction,
pour en préciser la fonction ou le résultat. Ils sont introduit
à la suite de deux caractères "slash" (//)
; tout ce qui est inclus entre ces caractères et la fin de la ligne
est considéré en commentaire. Les seconds permettent de préciser
le contenu d'un bloc d'instruction, éventuellement, l'algorithme
utilisé, etc. Ces types de commentaires réclament donc plusieurs
lignes. Le début du commentaire est précisé par /*,
tandis que la fin l'est par */. Ce type de
commentaire disposant d'une marque de début et d'une marque de fin,
il pourra aussi être utilisé pour des commentaires très
courts, au contraire, en particulier à l'intérieur même
d'une instruction (comme nous le verrons en exemple.
Il convient de noter aussi la grande utilité
de ces commentaires pour déboguer les programmes. Ils permettent
soit de transformer en commentaires certaines parties sujettes à
provoquer des erreurs pour vérifier le reste, soit de prévoir
des traces de mise au point que l'on peut à loisir faire disparaître
simplement en les transformant en commentaires.
Exemple
:
var Rayon = 3; //
Initialisation de Rayon
/* On va à présent s'étendre
dans un long commentaire afin d'expliquer ce que l'on va
bien pouvoir faire avec Rayon......*/
var S = 3.14 /*
valeur de Pi */
* Rayon * Rayon;
Nous ne reviendrons pas ici sur les
commentaires conditionnels que nous avons déjà
présentés au chapitre précédent.
4 - Les caractères
spéciaux.
Comme en C, C++, Java ou Perl, JavaScript autorise
la représentation de caractères particuliers à
l'intérieur d'une chaîne de caractères. Pour pouvoir
obtenir ces représentations, on utilise le caractère backslash
(\) suivi d'un autre caractère. Nous avons vu que JavaScript
dispose de deux caractères différents pour limiter les
chaînes, ce qui est bien agréable lorsque la chaîne
elle-même nécessite l'utilisation d'un de ces caractères,
comme par exemple dans "L'apprentissage de JavaScript est aisé",
ou encore ' Le professeur a dit : "Étudiez sérieusement
!" '. Mais nous rencontrerons de nombreuses situations où
cela ne suffira plus. Dans ce cas, nous pourrons utiliser les caractères \'
ou \" pour signifier l'occurrence d'une simple apostrophe ou de
guillemets comme dans : "Le professeur a dit : \"L\'apprentissage
de JavaScript est aisé !\" ".
Voici la liste de ces caractères spéciaux
ainsi que leur signification :
Séquence
\b
\n
\f
\t
\r
\\
\'
\"
\
\x
\u
Caractère représenté
Backspace - retour arrière
d'un caractère
Newline - Saut de ligne
Form feed - Nouvelle page
Tab - Tabulation
Return - Retour chariot
Backslash - Le caractère backslash lui-même
Single quote - Apostrophe
Double quote - Guillemets
N'importe quel caractère dont représente
le code octal (3 chiffres)
N'importe quel caractère dont représente le
code hexadécimal (2 chiffres)
N'importe quel caractère dont représente
le code Unicode (4 chiffres hexa)
Il est à noter que pour tout caractère autre
que ceux indiqués ci-dessus, le fait qu'il apparaisse précédé
d'un backslash ne change absolument rien. Le backslash est ignoré
et le caractère apparaît normalement.
Une application très simple mais cependant fort utile pour coder les
caractères non standard... Elle vous donnera l'unicode hexa
d'un caractère.
Table des unicodes des caractères
les plus couramment utilisés en Français :
é
00E9
0153
à
00E0
è
00E8
ù
00F9
â
00E2
ê
00EA
î
00EE
ô
00F4
û
00FB
ä
00E4
ë
00EB
ï
00EF
ö
00F6
ü
00FC
L'utilisation de ces unicodes dans les navigateurs
récents est préférable dans certaines utilisations
au bricolage du type é=é
car ces unicodes sont interprétés de façon homogènes
dans toutes les utilisations. Par exemple, supposons que l'on affecte
à une variable S la chaîne "Le dîner sera
prêt à l'heure" et que la valeur de cette variable
soit utilisée en défilement.
En utilisant l'Unicode, on aura S
= "Le d\u00EEner sera pr\u00EAt \u00E0 l'heure " ;
avec l'autre codage, on aura S = "Le dîner
sera prêt à l'heure ".
Voyons ce que cela donne en défilement (suppression
de caractère de tête + rajout à la fin + écriture)
:
On constate que chaque groupe désignant
un caractère Unicode est effectivement réduit à
un seul caractère qui peut ainsi être ôté
en début de chaîne à chaque itération,
ce qui n'est pas le cas pour l'autre codage.
PS : A noter que les codes Unicode
correspondant à l'alphabet latin et à son extension
pour les caractères accentués se situent entre les
codes 0000 et 00FF et correspondent exactement aux codes ASCII que
l'on connaît bien. Par exemple \u00ea peut être remplacé
par \xea pour représenter "ê" lorsque le
système de codage est l'Occidental-Latin.
5 - Les valeurs
numériques spéciales
L'objet JavaScript Number
possède pour propriétés des valeurs permettant
de représenter soit des grandeurs non représentables,
soit les valeurs extrêmes pouvant être atteintes, soit une
indication permettant de signaler ou de tester le fait qu'une variable
n'est pas un nombre.
Exemple
:
Afficher Number.MAX_VALUE
Afficher
Number.MIN_VALUE
Afficher
"chaine" * 1
Afficher
1/0
Afficher
-1/0
6 - Des booléens
qui sortent de l'ordinaire
Alors que les littéraux chaînes et les
littéraux numériques peuvent avoir une infinité
de valeurs, les booléens, eux, n'ont que deux valeurs possibles
true ou false.
Cela n'est pas une nouveauté et JavaScript, pour cela, ne se
différencie pas des autres langages. Il convient toutefois d'ajouter
que les littéraux autres que les littéraux
booléens ont eux-mêmes une valeur booléenne
et il vaut mieux la connaître.
Pour tester toutes les valeurs que vous voulez, vous n'avez
qu'à cliquer ici......
Ainsi que vous pouvez le constater, seule la valeur
numérique nulle quelle que soit sa forme (entière, réelle
en virgule fixe ou flottante) a une valeur booléenne false,
toutes les autres ayant la valeur true.
null a une valeur booléenne false
et toutes les chaînes ont une valeur booléenne true.
Ce dernier point mérite d'être souligné car JavaScript
est capable d'interpréter toute chaîne de caractères
contenant des chiffres comme des nombres en fonction du contexte
dans lequel la chaîne est utilisée. Par exemple, pour mettre
en évidence la valeur NaN dans
l'exemple ci-dessus, on a fait écrire "chaîne"
* 1, ce qui a provoqué l'apparition de la valeur NaN.
Mais si l'on avait exécuté alert("12"*2/3),
on aurait bien obtenu le résultat 8.
C'est donc bien que "12" a
été interprété comme la valeur 12.
Ces explications pour mettre en garde contre le piège
qui pourrait consister à penser qu'en conséquence, la
chaîne "0" va avoir la
valeur de vérité false
comme le chiffre correspondant. Il n'en est rien ! "0"
ne déroge pas à la règle indiquant que
les chaînes quelles qu'elles soient ont pour valeur booléennetrue.
Vous pouvez vérifier tout cela par le lien
précédent.
7 - Les
objets
La plupart des langage récents (C++, Java, JavaScript,...)
ont pris le parti d'être orientés
objet, par opposition aux langages plus anciens (Fortran, Basic,
Pascal, C, ...) qui sont eux orientés
action. Dans ces langages, la priorité est faite aux données
(les objets), à leur structure
(les propriétés), à
la façon d'y accéder pour en extraire tout ou partie de
l'information qu'elles contiennent (les méthodes),
à la façon de les créer (les constructeurs
- qui sont des méthodes particulières-).
Cette organisation a un immense intérêt pour
les langages utilisés sur internet car s'exécutant sur les
machines clients, ils se doivent d'offrir un niveau de garantie
de sécurité irréprochable
afin qu'une applette (Java) ou qu'un script
ne prenne pas des "libertés" préjudiciables au client
(préservation de la confidentialité
et de l'intégrité des données). En l'occurrence,
ces langages et plus exactement leur compilateur (respectivement interpréteur),
veillent à ce que seules les méthodes définies associées
aux objets auxquels elles appartiennent et donc, sur lesquels elles s'exercent,
puissent être activées. «Ainsi, on ne
peut pas faire n'importe quoi sur n'importe quoi ! »
En JavaScript, tout est objet ! On distingue toutefois
parmi ceux-ci, deux types : les objets de type
primitif et les objets de type composé.
Les premiers sont ceux qui se résument à une valeur unique
: les nombres, les booléens et les chaînes. Les seconds
(tableaux, fonctions ou... objets) comportent plusieurs valeurs (propriétés),
chacune bénéficiant d'un nom et d'une valeur, l'ensemble
réuni en une seule entité (l'objet), elle aussi identifiée
par un nom. L'accès à une propriété (pour
lui affecter ou en lire sa valeur) devra obligatoirement préciser
en premier lieu le nom de l'objet suivi du nom de la propriété
concernée. Nous pourrons affecter à
une propriété n'importe quel type d'objet (objets
de type primitif ou de type composé)
Autre point d'intérêt différenciant
les types primitifs des types composés : les premiers sont manipulés
par valeur, tandis que les autres les sont
par référence. Cela se justifient
parfaitement si l'on considère que des objets de type composé
peuvent contenir un très grand nombre de valeurs (les tableaux, par
exemple) et qu'il serait donc totalement inefficace de les traiter par valeur,
vu l'espace mémoire qui serait utilisé en pure perte.
La question peut toutefois se poser pour les chaînes, qui bien que
pouvant comporter un nombre de caractères conséquent, sont
de type primitif. Effectivement, c'est une bonne question ! ;-))
Attention
! Ce qui vient d'être dit mérite une mise
au point ! Certains pourraient assimiler passage par valeur et passage par
référence avec ce qu'il on déjà vu dans certains
langages en ce qui concerne le passage de paramètres à des
fonctions, à savoir : toute modification à l'intérieur
d'une fonction d'une variable passée par valeur n'aura pas de répercussion
à l'extérieur, tandis que pour une variable passée par
référence, la modification sera retransmise.
Ici, il s'agit de l'entité passée en paramètre. Quand
on parle de référence, il s'agit d'un pointeur
vers l'objet et non pas de l'objet lui-même. Si une (ou plusieurs)
valeurs de cet objets sont modifiés via la référence,
bien sûr, ces modifications affecteront l'objet. Par contre, si dans
une fonction, cette référence est surchargée par une
autre référence à un autre objet, cette modification
demeurera locale. Pour ceux que cela perturbe, disons que le passage s'opère
toujours par valeur, mais dans le cas des objets composés, cette valeur
est une référence vers l'objet. C'est bon comme cela ?...
Bien que nous n'ayons pas encore étudié les
objets de type composé, voici un exemple simple à comprendre,
qui illustre la précédente mise en garde. Nous allons considérer
un tableau contenant les valeurs 1, 2, 3, 4 et 5. Ce tableau est passé
en paramètre à une fonction qui, dans un premier temps va substituer
à la valeur 3 la valeur 100, puis affecter à ce tableau (via
son pointeur de référence) un autre tableau contenant les valeurs
9, 8, 7, 6 et 5. Voici le programme et son exécution.
var Tab=new Array(1,2,3,4,5);
Modifier(Tab);
Afficher(Tab);
function Modifier(T){
var AutreT=new Array(9,8,7,6,5);
T[2]=100;
T=AutreT;
Afficher(T);
}
8 - Les autres
objets de type composé
Il convient de mentionner enfin deux types d'objets composés
: les fonctions et les tableaux
dont nous avons eu un avant goût dans les exercices précédents
. Nous ne rentrerons pas ici dans le détail de ces objets. Simplement,
nous nous devions d'en parler car ils constituent des données au même
titre que les nombres ou les chaînes. En particulier, contrairement
à tous les autres langages (dont Java), les fonctions ont à
la fois un statut opérationnel exécutable, mais aussi un statut
de données ce qui apporte une grande souplesse au langage en ce sens
qu'elles peuvent être affectées à une variable, un élément
de tableau, une propriété d'objet (méthode), passées
en paramètre d'une autre fonction, etc. En ce qui concerne les tableaux,
la particularité de JavaScript est d'autoriser ceux-ci à contenir
des objets de types différents. Un tableau peut ainsi contenir simultanément
et indifféremment des nombres, des chaînes, des fonctions, des
tableaux, bref n'importe quelles sortes d'objets.
Ajoutons enfin que fonctions et tableaux peuvent être
définis sous une forme littérale comme nous avons pu le
voir précédemment.