II. Variables, Objets, Types et Valeurs▲
II-A. Les identificateurs▲
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.
var MonIdent =
12
;
// déclaration explicite, type numérique
var i =
3
;
// déclaration explicite, type numérique
i =
i *
monIdent;
// 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.
Mon_Ident
$id31
_entier
valeur
É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.
II-B. Les littéraux▲
Les valeurs constantes affectées à des variables ou intervenant dans des comparaisons à celles-ci sont appelées 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. À 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).
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.
3
.
14
// réel fixe
48
// entier décimal
.
327E+
4
// réel flottant
0357
// entier octal
0x4f7C
// entier hexadécimal
'C
\'
est une cha
\u00ee
ne'
"... celle-l
\u00e0
aussi !!"
false // booléen
null
0358
// entier décimal (chiffre 8)
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
[
0
,
8
,
3
,
7
]
// tableau d'entiers
{
Nom
:
"Terieur"
,
Prenom
:
"Alain"
}
// Propriétés d'objet
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 JavaScript, 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 erreurs 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
var MonIdent =
12
var i =
3
//Instruction bien analysée
2
*
MonIdent/
2
// 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)
var j =
8
// L'identificateur j est affecté à 8 (partie du littéral 81...)
1
*
Mon //Erreur : identificateur Mon non défini !!!!... et c'est tout !!!!
Ident //Erreur : identificateur Ident non défini !!!!
var Nom =
"Alain Terieur //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.
II-C. 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. Ils 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êtes 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'a é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 introduits à 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'instructions, é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.
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.
II-D. 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, 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 (trois chiffres) N'importe quel caractère dont •• représente le code hexadécimal (deux chiffres) N'importe quel caractère dont •••• représente le code Unicode (quatre 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ène 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.
P.-S. : à 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.
II-E. 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.
Afficher Number.MAX_VALUE |
|
Afficher
Number.MIN_VALUE |
|
Afficher
"chaine" * 1 |
|
Afficher
1/0 |
|
Afficher -1/0 |
|
II-F. 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éenne true.
Vous pouvez vérifier tout cela :
lienII-G. Les objets▲
La plupart des langages 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 justifie 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 important, sont de type primitif. Effectivement, c'est une bonne question ! ;-))
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'ils ont 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 objet sont modifiées 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);
}
II-H. 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.