Les objets vous permettent de stocker des collections de valeurs cl. Cest trs bien.
Mais assez souvent, nous trouvons quil nous faut une collection ordonne, o nous avons un 1er, un 2me, un 3me lment, etc. Par exemple, nous avons besoin de cela pour stocker une liste de quelque chose : utilisateurs, trucs, lments HTML, etc.
Il nest pas pratique dutiliser un objet ici, car il ne fournit aucune mthode pour grer lordre des lments. Nous ne pouvons pas insrer une nouvelle proprit entre celles existantes. Les objets ne sont tout simplement pas destins un tel usage.
Il existe une structure de donnes spciale appele Array (tableau), pour stocker les collections ordonnes.
Dclaration
Il existe deux syntaxes pour crer un tableau vide :
let arr = new Array();
let arr = [];
La plupart du temps cest la deuxime syntaxe qui est utilise. Nous pouvons fournir des lments initiaux entre parenthses :
let fruits = ["Apple", "Orange", "Plum"];
Les lments de tableau sont numrots en commenant par zro.
On peut obtenir un lment par son numro grace aux crochets :
let fruits = ["Apple", "Orange", "Plum"];
alert( fruits[0] ); // Apple
alert( fruits[1] ); // Orange
alert( fruits[2] ); // Plum
Nous pouvons remplacer un lment :
fruits[2] = 'Pear'; // maintenant ["Apple", "Orange", "Pear"]
Ou en ajouter un nouveau au tableau :
fruits[3] = 'Lemon'; // maintenant ["Apple", "Orange", "Pear", "Lemon"]
Le nombre total dlments dans le tableau est sa length (longueur) :
let fruits = ["Apple", "Orange", "Plum"];
alert( fruits.length ); // 3
Nous pouvons galement utiliser un alert pour afficher lensemble du tableau :
let fruits = ["Apple", "Orange", "Plum"];
alert( fruits ); // Apple,Orange,Plum
Un tableau peut stocker des lments de tout type.
Par exemple :
// mlange de valeurs
let arr = [ 'Apple', { name: 'John' }, true, function() { alert('hello'); } ];
// rcupre l'objet l'index 1 et montre ensuite son nom
alert( arr[1].name ); // John
// affiche la fonction l'index 3 et l'excute la
arr[3](); // hello
Un tableau, comme pour un objet, peut se terminer par une virgule :
let fruits = [
"Apple",
"Orange",
"Plum",
];
Le style virgule de fin facilite linsertion et la suppression dlments, car toutes les lignes se ressemblent.
Rcuprer les derniers lments avec at
Disons que nous voulons le dernier lment du tableau.
Certains langages de programmation permettent lutilisation dindex ngatifs pour a, comme fruits[-1].
Tandis quen JavaScript a ne fonctionnera pas. Le rsultat sera undefined, parce que lindex dans les crochets est trait littralement.
Nous pouvons calculer explicitement lindex du dernier lment et donc y accder: fruits[fruits.length - 1].
let fruits = ["Apple", "Orange", "Plum"];
alert( fruits[fruits.length-1] ); // Plum
Un peu lourd, nest-ce pas ? Nous devons crire le mme nom de variable deux fois.
Heureusement, il y a une syntaxe plus courte : fruits.at(-1) :
let fruits = ["Apple", "Orange", "Plum"];
// Identique fruits[fruits.length-1]
alert( fruits.at(-1) ); // Plum
En dautres termes, arr.at(i):
- est exactement identique
arr[i], sii >= 0. - pour les valeurs ngatives de
i, a recule depuis la fin du tableau.
Les mthodes pop/push, shift/unshift
Une queue (file dattente) est lune des utilisations les plus courantes pour les tableaux. En informatique, cela signifie une collection ordonne dlments qui supporte deux oprations :
pushajoute un lment la fin.shiftenlve un lment depuis le dbut, en faisant avancer la file dattente, de sorte que le deuxime lment devienne le premier.
Les tableaux prennent en charge les deux oprations.
En pratique, nous en avons besoin trs souvent. Par exemple, une file dattente de messages devant tre affichs lcran.
Il y a un autre cas dutilisation pour les tableaux la structure de donnes nomme stack.
Il supporte deux oprations :
pushajoute un lment la fin.popenlve un lment de la fin.
Ainsi, de nouveaux lments sont ajouts ou enlevs toujours partir de la fin.
Un stack (pile) est gnralement illustre par un jeu de cartes. De nouvelles cartes sont ajoutes ou enleves par le haut :
Pour les stacks (piles), le dernier lment envoy est reu en premier, cest le principe LIFO (Last-In-First-Out, dernier entr, premier sorti). Pour les files dattente, nous avons FIFO (First-In-First-Out, premier entr, premier sorti).
Les tableaux en JavaScript peuvent fonctionner la fois en queue et en stack. Ils vous permettent dajouter ou supprimer des lments la fois par le dbut ou par la fin.
En informatique, la structure de donnes qui permet cela sappelle deque.
Mthodes qui fonctionnent avec la fin du tableau :
pop-
Extrait le dernier lment du tableau et le renvoie :
let fruits = ["Apple", "Orange", "Pear"]; alert( fruits.pop() ); // supprime "Pear" et l'alerte alert( fruits ); // Apple, OrangeLes deux mthodes
fruits.pop()etfruits.at(-1)renvoient le dernier lment du tableau, maisfruits.pop()modifie galement le tableau en supprimant llment. push-
Ajoute llment la fin du tableau :
let fruits = ["Apple", "Orange"]; fruits.push("Pear"); alert( fruits ); // Apple, Orange, PearLappel de
fruits.push(...)est galfruits[fruits.length] = ....
Mthodes qui fonctionnent avec le dbut du tableau :
shift-
Extrait le premier lment du tableau et le renvoie :
let fruits = ["Apple", "Orange", "Pear"]; alert( fruits.shift() ); // supprime "Apple" et l'alerte alert( fruits ); // Orange, Pear unshift-
Ajoute llment au dbut du tableau :
let fruits = ["Orange", "Pear"]; fruits.unshift("Apple"); alert( fruits ); // Apple, Orange, Pear
Les mthodes push et unshift peuvent ajouter plusieurs lments la fois :
let fruits = ["Apple"];
fruits.push("Orange", "Peach");
fruits.unshift("Pineapple", "Lemon");
// ["Pineapple", "Lemon", "Apple", "Orange", "Peach"]
alert( fruits );
Les internes
Un tableau est un type dobjet spcial. Les crochets utiliss pour accder la proprit arr[0] proviennent en fait de la syntaxe de lobjet. Cest essentiellement la mme chose que obj[key], o arr est lobjet, tandis que les nombres sont utiliss comme cls.
Ils tendent les objets en fournissant des mthodes spciales pour travailler avec des collections ordonnes de donnes ainsi que la proprit length. Mais au fond cest toujours un objet.
Noubliez pas quil ny a que huit types de base en JavaScript (voir le chapitre Les types de donnes pour plus dinfos). Array est un objet et se comporte donc comme un objet.
Par exemple, il est copi par rfrence :
let fruits = ["Banana"]
let arr = fruits; // copier par rfrence (deux variables font rfrence au mme tableau)
alert( arr === fruits ); // true
arr.push("Pear"); // modifie le tableau par rfrence
alert( fruits ); // Banana, Pear - 2 items maintenant
Mais ce qui rend les tableaux vraiment spciaux, cest leur reprsentation interne. Le moteur tente de stocker ses lments dans une zone de mmoire contigu, lun aprs lautre, exactement comme le montrent les illustrations de ce chapitre. Il existe galement dautres optimisations permettant de faire fonctionner les tableaux trs rapidement.
Mais ils se cassent tous si nous arrtons de travailler avec un tableau comme avec une collection ordonne et commenons le travailler comme sil sagissait dun objet normal.
Par exemple, techniquement, nous pouvons faire ceci :
let fruits = []; // crer un tableau
fruits[99999] = 5; // assigne une proprit avec un index beaucoup plus grand que sa longueur
fruits.age = 25; // crer une proprit avec un nom arbitraire
Cest possible, car les tableaux sont des objets leur base. Nous pouvons leur ajouter des proprits.
Mais le moteur verra que nous travaillons avec le tableau comme avec un objet normal. Les optimisations spcifiques un tableau ne sont pas adaptes ce type de situation et seront dsactives. Leurs avantages disparaissent.
Les moyens de casser un tableau :
- Ajouter une proprit non numrique comme
arr.test = 5. - Faire des trous, comme ajouter
arr[0]et ensuitearr[1000](et rien entre eux). - Remplire le tableau dans lordre inverse, comme
arr[1000],arr[999]etc.
Veuillez considrer les tableaux comme des structures spciales pour travailler avec les donnes ordones. Ils fournissent des mthodes spciales pour cela. Les tableaux sont soigneusement rgls dans les moteurs JavaScript pour fonctionner avec des donnes ordonnes contigus, veuillez les utiliser de cette manire. Et si vous avez besoin de cls arbitraires, il y a de fortes chances pour que vous ayez rellement besoin dun objet rgulier {}.
Performance
Les mthodes push/pop vont vite, alors que shift/unshift sont lentes.
Pourquoi est-il plus rapide de travailler avec la fin dun tableau quavec son dbut ? Voyons ce qui se passe pendant lexcution :
fruits.shift(); // prends 1 lment du dbut
Il ne suffit pas de prendre llment avec le nombre 0. Dautres lments doivent galement tre renumrots.
Lopration shift doit faire 3 choses :
- Supprimer llment avec lindex
0. - Dplacer tous les lments gauche, les renumroter de lindex
10, de21, etc. - Mettre jour la proprit
length.
Plus il y a dlments dans le tableau, plus il y faut de temps pour les dplacer, plus il y a doprations en mmoire.
La mme chose se produit avec unshift. Pour ajouter un lment au dbut du tableau, nous devons dabord dplacer les lments existants vers la droite, en augmentant leur index.
Et quen est-il avec push/pop ? Ils nont pas besoin de dplacer quoi que ce soit. Pour extraire un lment de la fin, la mthode pop nettoie lindex et raccourcit length.
Les actions pour lopration pop :
fruits.pop(); // enleve 1 lment de la fin
La mthode pop na pas besoin de dplacer quoi que ce soit, car les autres lments conservent leurs index. Cest pourquoi cest extrmement rapide.
La mme chose avec la mthode push.
Boucles
Lune des mthodes les plus anciennes pour cycler des lments de tableau est la boucle for sur les index :
let arr = ["Apple", "Orange", "Pear"];
for (let i = 0; i < arr.length; i++) {
alert( arr[i] );
}
Mais pour les tableaux, il existe une autre forme de boucle, for..of :
let fruits = ["Apple", "Orange", "Plum"];
// itre sur des lments de tableau
for (let fruit of fruits) {
alert( fruit );
}
Le for..of ne donne pas accs au numro de llment actuel, mais sa valeur, mais dans la plupart des cas, cela suffit. Et cest plus court.
Techniquement, comme les tableaux sont des objets, il est galement possible dutiliser for..in :
let arr = ["Apple", "Orange", "Pear"];
for (let key in arr) {
alert( arr[key] ); // Apple, Orange, Pear
}
Mais cest en fait une mauvaise ide. Il y a des problmes potentiels avec cela :
-
La boucle
for..initre sur toutes les proprits, pas seulement les proprits numriques.Il existe des objets dits array-like dans le navigateur et dans dautres environnements, qui ressemblent des tableaux. Cest--dire quils ont les proprits
lengthet index, mais ils peuvent galement avoir dautres proprits et mthodes non numriques, dont nous navons gnralement pas besoin. La bouclefor..inles listera cependant. Donc, si nous devons travailler avec des objets de type tableau, ces proprits supplmentaires peuvent devenir un problme. -
La boucle
for..inest optimise pour les objets gnriques, pas pour les tableaux, elle est 10-100 fois plus lente. Bien sr, cest encore trs rapide. Lacclration peut nimporter que dans les goulots dtranglement ou sembler hors de propos. Mais il faut quand mme tre conscient de la diffrence.
En rgle gnrale, nous ne devrions pas utiliser for..in pour les tableaux.
Un mot propos de length
La proprit length est automatiquement mise jour lorsque nous modifions le tableau. Pour tre prcis, il ne sagit pas du nombre de valeurs du tableau, mais du plus grand index numrique plus un.
Par exemple, un seul lment avec un grand index donne une grande longueur :
let fruits = [];
fruits[123] = "Apple";
alert( fruits.length ); // 124
Notez que nous nutilisons gnralement pas de tableaux de ce type.
Une autre chose intressante propos de la proprit length est quelle est accessible en criture.
Si nous laugmentons manuellement, rien dintressant ne se produit. Mais si nous le diminuons, le tableau est tronqu. Le processus est irrversible, voici lexemple :
let arr = [1, 2, 3, 4, 5];
arr.length = 2; // tronque 2 lments
alert( arr ); // [1, 2]
arr.length = 5; // retourne la length d'origine
alert( arr[3] ); // undefined: les valeurs ne reviennent pas
Ainsi, le moyen le plus simple pour effacer le tableau est arr.length = 0;.
new Array()
Il y a une syntaxe supplmentaire pour crer un tableau :
let arr = new Array("Apple", "Pear", "etc");
Il est rarement utilis, car les crochets [] sont plus courts. En outre, il comporte une caractristique dlicate.
Si new Array est appel avec un seul argument qui est un nombre, il cre un tableau sans lments, mais avec la longueur donne.
Voyons comment on peut se tirer une balle dans le pied :
let arr = new Array(2); // va-t-il crer un tableau de [2] ?
alert( arr[0] ); // undefined! pas d'lments.
alert( arr.length ); // length 2
Pour viter de telles surprises, nous utilisons gnralement des crochets, sauf si nous savons vraiment ce que nous faisons.
Tableaux multidimensionnels
Les tableaux peuvent avoir des lments qui sont aussi des tableaux. On peut lutiliser pour des tableaux multidimensionnels, pour stocker des matrices :
let matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
alert( matrix[1][1] ); // 5, l'lment central
toString
Les tableaux ont leur propre implmentation de la mthode toString qui renvoie une liste dlments spars par des virgules.
Par exemple :
let arr = [1, 2, 3];
alert( arr ); // 1,2,3
alert( String(arr) === '1,2,3' ); // true
Aussi, essayons ceci :
alert( [] + 1 ); // "1"
alert( [1] + 1 ); // "11"
alert( [1,2] + 1 ); // "1,21"
Les tableaux nont pas de Symbol.toPrimitive, ni de valueOf viable, ils implmentent uniquement la conversion toString, donc ici [] devient une chane vide, [1] devient "1" et [1,2] devient "1,2".
Lorsque loprateur binaire plus + ajoute quelque chose une chane, il la convertit galement en chane, de sorte que ltape suivante se prsente comme suit :
alert( "" + 1 ); // "1"
alert( "1" + 1 ); // "11"
alert( "1,2" + 1 ); // "1,21"
Ne comparez pas les tableaux avec ==
Les tableaux en JavaScript, contrairement certains autres langages de programmation, ne doivent pas tre compars avec loprateur ==.
Cet oprateur na pas de traitement spcial pour les tableaux, il fonctionne avec eux comme avec nimporte quel objet.
Rappelons les rgles :
- Deux objets sont gaux
==uniquement sils font rfrence au mme objet. - Si lun des arguments de
==est un objet, et lautre est une primitive, alors lobjet est converti en primitif, comme expliqu dans le chapitre Conversion d'objet en primitive. - lexception de
nulletundefinedqui sgalent==lun lautre et rien dautre.
La comparaison stricte === est encore plus simple, car elle ne convertit pas les types.
Donc, si nous comparons des tableaux avec ==, ils ne sont jamais les mmes, sauf si nous comparons deux variables qui rfrencent exactement le mme tableau.
Par exemple :
alert( [] == [] ); // false
alert( [0] == [0] ); // false
Ces tableaux sont des objets techniquement diffrents. Donc, ils ne sont pas gaux. Loprateur == ne fait pas de comparaison lment par lment.
La comparaison avec les primitives peut galement donner des rsultats apparemment tranges :
alert( 0 == [] ); // true
alert('0' == [] ); // false
Ici, dans les deux cas, nous comparons une primitive un objet tableau. Ainsi, le tableau [] est converti en primitive des fins de comparaison et devient une chane vide ''.
Ensuite, le processus de comparaison se poursuit avec les primitives, comme dcrit dans le chapitre Les conversions de types :
// aprs que [] soit converti vers ''
alert( 0 == '' ); // true, car '' est converti en nombre 0
alert('0' == '' ); // false, pas de conversion de type, diffrentes chanes de caractres
Alors, comment comparer des tableaux ?
Cest simple, nutilisez pas loprateur ==. Au lieu de cela, comparez-les lment par lment dans une boucle ou en utilisant les mthodes ditration expliques dans le chapitre suivant.
Rsum
Array est un type dobjet spcial, adapt au stockage et la gestion des lments de donnes ordonnes.
-
La dclaration :
// crochets (habituel) let arr = [item1, item2...]; // new Array (exceptionnellement rare) let arr = new Array(item1, item2...);Lappel de
new Array(number)cre un tableau de longueur donne, mais sans lments. -
La proprit
lengthest la longueur du tableau ou, plus prcisment, son dernier index numrique plus un. Il est auto-ajust par les mthodes de tableau. -
Si nous raccourcissons
lengthmanuellement, le tableau est tronqu.
Obtenir les lments:
- nous pouvons obtenir un lment par son index, comme
arr[0] - nous pouvons galement utiliser la mthode
at(i)qui autorise les index ngatifs. Pour les valeurs ngatives dei, il recule partir de la fin du tableau. Sii >= 0, cela fonctionne commearr[i].
Nous pouvons utiliser un tableau comme deque avec les oprations suivantes:
push(...items)ajouteitemsla fin.pop()supprime llment de la fin et le renvoie.shift()supprime llment du dbut et le renvoie.unshift(... items)ajoute desitemsau dbut.
Pour boucler sur les lments du tableau :
for (let i = 0; i <arr.length; i++)fonctionne le plus rapidement, compatible avec les anciens navigateurs.for (let item of arr)la syntaxe moderne pour les lments uniquement.pour (let i in arr)ne jamais utiliser.
Pour comparer des tableaux, nutilisez pas loprateur == (ainsi que >, < et autres), car ils nont pas de traitement spcial pour les tableaux. Ils les traitent comme nimporte quel objet, et ce nest pas ce que nous voulons habituellement.
A la place, vous pouvez utiliser la boucle for..of pour comparer les tableaux lment par lment.
Nous continuerons avec les tableaux et tudierons dautres mthodes pour ajouter, supprimer, extraire des lments et trier des tableaux dans le prochain chapitre Mthodes de tableau.
Commentaires
<code>, pour plusieurs lignes enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen)