Nous avons introduit ce concept précédemment
lorsque nous avons présenté les divers types d'objets,
et en particulier, les objets dits composés.
Nous avons aussi parlé de tableaux associatifs dans le précédent
chapitre §5.
Il est important de souligner qu'il n'y a rien
à voir entre les deux ! Alors que le second constitue
une façon d'accéder à des objets/propriétés
via une chaîne de caractères les désignant, le premier,
auquel nous nous intéresserons dans ce chapitre, sont des tableaux
au sens habituel du terme dans un langage de programmation, c'est à
dire, des objets qui permettent d'associer une série de valeurs
à une série de nombres entiers. On dit que la série
de valeurs est indicée(indexée)
et chacune est accessible au moyen d'un nombre,
la valeur de l'indice (index)
lui correspondant.
A noter toutefois qu'à la différence d'autres langages de
programmation, en JavaScript, les éléments contenus dans un
même tableau peuvent être de types différents.
2
- Comment définir un tableau ?
La création d'un objet de type Array (que nous
appellerons dorénavant tableau) s'opère "canoniquement"
à l'aide de l'opérateur new suivi
du constructeur Array. Cette méthode
peut revêtir trois allures différentes : soit on définit
seulement un objet tableau, sans préciser sa taille ni son contenu,
soit on précise sa taille, mais pas son contenu, soit son contenu et
donc, implicitement, sa taille.
Exemple
:
var MonTableau1 = new Array();
var MonTableau2 = new Array(15);
var MonTableau3 = new Array(1,"Salut",3.14,void 0);
A ce point il importe de préciser quatre choses :
Tout indice de tableau débute en 0 (comme en C, C++, Java, etc.)
;
la taille d'un tableau n'est pas figée par sa définition
ou son initialisation. Elle est dynamique.
Le script qui suit vous en donne la preuve !!!
A chaque instant, la taille d'un tableau peut être connue en invoquant
la propriété length de l'objet
correspondant à ce tableau. (Nous verrons, à la fin de ce
chapitre, un exercice mettant en jeu la possibilité d'accéder
à cette propriété non seulement en lecture, mais aussi
en écriture).
L'accès à un élément d'un
tableau Tab s'opère en faisant suivre
l'identificateur représentant la référence vers ce tableau
(ici Tab) d'une paire de crochets (ouvrant et fermant), l'opérateur
[ ], contenant une expression arithmétique s'évaluant
par un entier positif ou nul et représentant la valeur de l'indice.
<script
language="JavaScript">
var T = new Array(3);
var S ="";
for (var i = 0; i < T.length; i++){
T[i] = i;
}
T[5] = "Pourtant, j'y suis";
for (var i = 0; i < T.length; i++){
S += "En " + i + " on trouve " + T[i] + "\n";
}
alert(S);
</script>
Par
ailleurs, on peut à la fois définir et initialiser un tableau
par sa forme littérale en précisant les valeurs successives
entre crochets.
Exemple
:
var MonTableau1 = [1,"Salut",3.14,null];
var MonTableau2 = [['essai',3],{h:3,v:12},2.7183];
var MonTableau3 = [function suc(x){return x+1},3];
La deuxième ligne de l'exemple ci-dessus montre que
l'on peut avoir des tableaux multidimensionnés ou plus exactement des
tableaux de tableaux. Pour accéder à un élément
de tableau de niveau inférieur, on aura recours à autant d'opérateurs
[ ] que de niveaux à traverser. Ainsi, dans l'exemple ci-dessus, l'écriture
MonTableau2[1][1] aura pour valeur
'essai', tandis que MonTableau2[1][2]
aura pour valeur 3.
3
- Les méthodes de la classe Array
La classe Array comporte un certain nombre de
méthodes dont plusieurs s'inspirent du langage Perl. Elles permettent
de manipuler les tableaux en les transposant en chaînes de caractères,
de les inverser, de les trier, d'en extraire des sous-tableaux, de les gérer
en tant que pile ou file, etc.
La méthode
join()
Cette méthode s'applique à un tableau et
a pour fonction de le transformer en une chaîne
de caractère dans laquelle les éléments sont
séparés par le caractère ",". La méthode
join peut recevoir un caractère optionnel spécifiant la
chaîne de caractères (éventuellement réduite
à un seul caractère) qui servira à séparer
les éléments. En conséquence, quel que soit le tableau
Tab, Tab.join()
est équivalent à Tab.join(",").
Il convient de noter (nous la verrons dans le prochain chapitre), la méthode
join() a une méthode inverse, split()
qui s'applique donc à un objets de type chaîne, pour transformer
celui-ci en éléments d'un tableau sur la base d'un séparateur
fourni en paramètre.
Nous allons imager ce duo par un exemple dans lequel à
partir d'une chaîne de caractères, puis d'un caractère
(ou d'une suite de caractères) auquel sera attribué le rôle
de séparateur. fournira alors les éléments du tableau
ainsi constitué. Sur la base d'une nouvelle chaîne de séparation,
la chaîne des éléments du tableau ainsi séparés
sera alors affichée;
La méthode concat()
Cette méthode réclame en argument le ou
les éléments qui seront rajoutés en fin de du tableau
référencé. L'absence d'argument ne provoque
pas d'erreur, mais présente un intérêt limité
;-) Elle retourne comme résultat un tableau comportant en tête
les éléments du tableau source et se terminant par les éléments
rajoutés. Dans le cas ou l'un des éléments est un
tableau, ce sont ses éléments qui sont rajoutés dans
l'ordre des indices croissants. Ce traitement n'est toutefois pas récursif
et si l'un des éléments rajoutés est un tableau de
tableau(x) l'aplatissement n'interviendra qu'au premier niveau. Voici
quelques exemples :
Comportement
de concat()...
Résultat
[3,"essai",pi=3.14].concat("ajout",.159)
[3,"essai",pi=3.14].concat([1,6],true)
[3,"essai",pi=3.14].concat([1,[6,true]])
[3,"essai"].concat(false,[[4,[6,2]],31])
La méthode reverse()
Comme son nom l'indique cette méthode tout simplement
inverse l'ordre des éléments du tableau
référencé. Le traitement s'opère dans
le tableau lui-même et ne nécessite donc pas une affectation
comme c'était le cas pour concat()
ou comme on le verra pour slice().
La méthode sort()
La méthode sort()
agit elle aussi sur le tableau référencé afin de
le trier. Par défaut, le tri s'opère
par ordre alphabétique après
transformation de tous les éléments qui le nécessitent
en chaîne de caractères.
Par exemple, [3,"essai",true,25,["prénom","nom"],false,"in"].sort()a
pour résultat : [25,3,["prénom","nom"],"essai",false,"in",true].
ATTENTION : On notera que l'ordre alphabétique n'intervient qu'au niveau le plus haut, celui du tableau effectivement trié. Le tableau enchassé n'est donc pas lui-même trié. En fait, l'ensemble formé par ce tableau enchassé est pris tel quel comme une chaîne de caractères et classé en conséquence.
Toutefois, pour avoir accès à des traitement
plus subtils, cette méthode peut recevoir un argument précisant
le critère de tri. Cet argument n'est autre qu'une fonction ayant
elle même deux arguments réputés être deux éléments quelconques
du tableau. La fonction va retourner une résultat négatif
si le premier argument doit trouver place avant le second et un résultat
positif dans le cas contraire. Dans le cas où les deux éléments
sont équivalents, la fonction devra rendre la valeur 0.
Soit un tableau de nombres, TabN=[9,12,77,31,14,54,111]
et un tableau de chaînes de caractères, TabC=["Pascal","java","C++","fortran","COBOL","algol"].
Examinons le tri utilisant diverses fonctions...
Cette méthode est utilisée pour extraire
un sous tableau du tableau référencé. Elle
reçoit deux arguments et le sous tableau extrait contient les éléments
du tableau source depuis l'indice désigné par le premier
argument jusqu'à l'indice désigné par le second argument
non compris. Dans le cas où un seul argument est
spécifié, le sous tableau contient tous les éléments
depuis l'indice ainsi désigné jusqu'à la fin du tableau.
Enfin, si un des arguments (ou les deux) sont négatifs, l'indice
désigné est relatif à la fin. Par exemple -1 désigne
le dernier élément, -2, l'avant dernier, etc.
Reprenons, par exemple, le tableau de nombres précédent,
TabN=[9,12,77,31,14,54,111].
Comportement
de slice()...
Résultat
TabN.slice(2,5)
TabN.slice(4)
TabN.slice(2,-3)
TabN.slice(-5,5)
TabN.slice(-6,-2)
Les utilisateurs d'Internet Explorer vont s'apercevoir,
dans les deux derniers exemples, que le comportement de la méthode
ne correspond pas à ce qui est décrit précédemment.
En effet, ce navigateur gère mal le premier paramètre lorsqu'il est négatif.
L'utilisation de cette méthode doit donc prendre cela en compte.
La méthode splice()
Comme pour reverse() et sort(),
cette méthode agit directement sur le tableau référencé(*).
Elle a pour fonction d'insérer et/ou retirer
des éléments du tableau. Le premier argument désigne
l'indice dans le tableau de l'élément de départ à
partir duquel la méthode va opérer (Comme pour slice()
on peut ici utiliser des indices relatifs à la fin). Le second
argument indique le nombre d'élément qui vont être retirés
à partir de l'indice désigné précédemment.
En l'absence de cet argument, c'est la fin du tableau qui est supprimée.
Les arguments suivants sont en fait les éléments qui doivent
être insérés dans le tableau à partir de la position
indiquée par le premier argument. La méthode délivre
une valeur en retour : le tableau constitué des éléments
supprimés (éventuellement vide).
Voyons quelques exemples d'utilisation de cette méthode
sur le tableau de chaînes de caractères TabC=["Pascal","java","C++","fortran","COBOL","algol"].
Cliquez de haut en bas afin de voir les transformations
successives du tableau TabC.
Comportement
de splice()...
Résultat
TabC.splice(2,1)
TabC.splice(4)
TabC.splice(1,1,"PL1","SmallTalk")
TabC.splice(3,0,["a",2],true)
(*) Cette méthode
apparue sous Netscape 4 n'est supportée par Internet explorer que
pour ses versions les plus récentes (>5.0x). A l'inverse des méthodes
précédentes, les résultats affichés ne sont pas
issus de véritables calculs mais sont des chaînes de caractères.
Il faut bien que les "Exploreurs" voient ce qu'ils ratent !....
Les quatre méthodes qui vont suivre permettent une utilisation de l'objet
tableau pour stoker et récupérer des valeurs, non pas par une
accès aléatoire via un indice, mais en gérant
le tableau sous forme d'une pile. La structure de pile est bien connue
des informaticiens. Il s'agit comme son nom l'indique d'un empilement de valeurs,
chaque valeur empilée venant recouvrir la précédente en
écriture et seule la dernière empilée étant accessible
en lecture. Il convient de préciser que l'ensemble de ces quatre méthodes
n'est pas supporté par Internet explorer, seul Netscape en autorisant
l'utilisation.
Les méthodes shift()
& unshift()
Ces deux méthodes permettent respectivement d'empiler
et de dépiler des valeurs quelconques dans un tableau en utilisant
systématiquement le début du tableau pour insérer
ou retirer des éléments. Cela impose donc obligatoirement
une translation des éléments du tableau, soit pour laisser
la place en indice 0 pour une valeur empilée, soit pour récupérer
la place libérée en indice 0 par une valeur dépilée.
Cela explique donc le nom de ces méthodes.
Alors que la méthode unshift()
réclame des arguments (les valeurs empilées dans l'ordre
de leur empilement), la méthode shift()
n'a elle aucun argument puisque par définition, c'est toujours
l'élément d'indice 0 qu'elle prélève. A noter
que bien évidemment c'est le tableau référencé
qui est lui-même affecté par l'utilisation de ces méthodes
qui, par ailleurs, retournent une valeur : pour unshift()
la valeur de retour indique la taille de la pile
; pour shift(), elle correspond à
l'élément prélevé en tête de pile.
Soit un tableau de nombres Tab=[],
voyons comment il se transforme par l'action de ces méthodes. Là
encore, pour respecter la chronologie, cliquez de haut en bas.
Comportement
de shift()/unshift()...
Résultat
V=Tab.unshift(22,9)
V=Tab.shift()
V=Tab.unshift(V%3,[V,V+1])
V=Tab.shift()
Les méthodes push()
& pop()
Alors que les deux méthodes précédentes
interviennent sur le début du tableau, push()
insère une valeur en fin de tableau, de même que pop()
prélève en fin de tableau. On évite ainsi le problème
de translation rencontré précédemment, par contre,
l'indice concerné est dynamique (la propriété length
sera fort utile). A ce sujet, même si Internet explorer ne dispose
pas de ces méthodes, il sera aisé de les définir.
Essayez, par exemple, de réécrire la méthode pop()
avant de regarder une proposition de solution.
A présent, prototypez la classe Array avec une méthode push().