Les objets vous permettent de stocker des collections de valeurs Ă clĂ©. Câest trĂšs bien.
Mais assez souvent, nous trouvons quâil nous faut une collection ordonnĂ©e, oĂč nous avons un 1er, un 2Ăšme, un 3Ăšme Ă©lĂ©ment, etc. Par exemple, nous avons besoin de cela pour stocker une liste de quelque chose : utilisateurs, trucs, Ă©lĂ©ments HTML, etc.
Il nâest pas pratique dâutiliser un objet ici, car il ne fournit aucune mĂ©thode pour gĂ©rer lâordre des Ă©lĂ©ments. Nous ne pouvons pas insĂ©rer une nouvelle propriĂ©tĂ© âentreâ celles existantes. Les objets ne sont tout simplement pas destinĂ©s Ă un tel usage.
Il existe une structure de données spéciale appelée Array (tableau), pour stocker les collections ordonnées.
Déclaration
Il existe deux syntaxes pour créer un tableau vide :
let arr = new Array();
let arr = [];
La plupart du temps câest la deuxiĂšme syntaxe qui est utilisĂ©e. Nous pouvons fournir des Ă©lĂ©ments initiaux entre parenthĂšses :
let fruits = ["Apple", "Orange", "Plum"];
Les éléments de tableau sont numérotés en commençant par zéro.
On peut obtenir un élément par son numéro grace aux crochets :
let fruits = ["Apple", "Orange", "Plum"];
alert( fruits[0] ); // Apple
alert( fruits[1] ); // Orange
alert( fruits[2] ); // Plum
Nous pouvons remplacer un élément :
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 dâĂ©lĂ©ments dans le tableau est sa length (longueur) :
let fruits = ["Apple", "Orange", "Plum"];
alert( fruits.length ); // 3
Nous pouvons Ă©galement utiliser un alert pour afficher lâensemble du tableau :
let fruits = ["Apple", "Orange", "Plum"];
alert( fruits ); // Apple,Orange,Plum
Un tableau peut stocker des éléments de tout type.
Par exemple :
// mélange de valeurs
let arr = [ 'Apple', { name: 'John' }, true, function() { alert('hello'); } ];
// récupÚre l'objet à l'index 1 et montre ensuite son nom
alert( arr[1].name ); // John
// affiche la fonction à l'index 3 et l'exécute 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 lâinsertion et la suppression dâĂ©lĂ©ments, car toutes les lignes se ressemblent.
RĂ©cupĂ©rer les derniers Ă©lĂ©ments avec âatâ
Disons que nous voulons le dernier élément du tableau.
Certains langages de programmation permettent lâutilisation dâindex nĂ©gatifs pour ça, comme fruits[-1].
Tandis quâen JavaScript ça ne fonctionnera pas. Le rĂ©sultat sera undefined, parce que lâindex dans les crochets est traitĂ© littĂ©ralement.
Nous pouvons calculer explicitement lâindex du dernier Ă©lĂ©ment et donc y accĂ©der: fruits[fruits.length - 1].
let fruits = ["Apple", "Orange", "Plum"];
alert( fruits[fruits.length-1] ); // Plum
Un peu lourd, nâest-ce pas ? Nous devons Ă©crire le mĂȘme 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 dâautres termes, arr.at(i):
- est exactement identique Ă
arr[i], sii >= 0. - pour les valeurs négatives de
i, ça recule depuis la fin du tableau.
Les méthodes pop/push, shift/unshift
Une queue (file dâattente) est lâune des utilisations les plus courantes pour les tableaux. En informatique, cela signifie une collection ordonnĂ©e dâĂ©lĂ©ments qui supporte deux opĂ©rations :
pushajoute un Ă©lĂ©ment Ă la fin.shiftenlĂšve un Ă©lĂ©ment depuis le dĂ©but, en faisant avancer la file dâattente, de sorte que le deuxiĂšme Ă©lĂ©ment devienne le premier.
Les tableaux prennent en charge les deux opérations.
En pratique, nous en avons besoin trĂšs souvent. Par exemple, une file dâattente de messages devant ĂȘtre affichĂ©s Ă lâĂ©cran.
Il y a un autre cas dâutilisation pour les tableaux â la structure de donnĂ©es nommĂ©e stack.
Il supporte deux opérations :
pushajoute un élément à la fin.popenlÚve un élément de la fin.
Ainsi, de nouveaux Ă©lĂ©ments sont ajoutĂ©s ou enlevĂ©s toujours Ă partir de la âfinâ.
Un stack (pile) est généralement illustrée par un jeu de cartes. De nouvelles cartes sont ajoutées ou enlevées par le haut :
Pour les stacks (piles), le dernier Ă©lĂ©ment envoyĂ© est reçu en premier, câest le principe LIFO (Last-In-First-Out, dernier entrĂ©, premier sorti). Pour les files dâattente, 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 dâajouter ou supprimer des Ă©lĂ©ments Ă la fois par le dĂ©but ou par la fin.
En informatique, la structure de donnĂ©es qui permet cela sâappelle deque.
Méthodes qui fonctionnent avec la fin du tableau :
pop-
Extrait le dernier élément du tableau et le renvoie :
let fruits = ["Apple", "Orange", "Pear"]; alert( fruits.pop() ); // supprime "Pear" et l'alerte alert( fruits ); // Apple, OrangeLes deux méthodes
fruits.pop()etfruits.at(-1)renvoient le dernier Ă©lĂ©ment du tableau, maisfruits.pop()modifie Ă©galement le tableau en supprimant lâĂ©lĂ©ment. push-
Ajoute lâĂ©lĂ©ment Ă la fin du tableau :
let fruits = ["Apple", "Orange"]; fruits.push("Pear"); alert( fruits ); // Apple, Orange, PearLâappel de
fruits.push(...)est Ă©gal Ăfruits[fruits.length] = ....
Méthodes qui fonctionnent avec le début du tableau :
shift-
Extrait le premier élément du tableau et le renvoie :
let fruits = ["Apple", "Orange", "Pear"]; alert( fruits.shift() ); // supprime "Apple" et l'alerte alert( fruits ); // Orange, Pear unshift-
Ajoute lâĂ©lĂ©ment au dĂ©but du tableau :
let fruits = ["Orange", "Pear"]; fruits.unshift("Apple"); alert( fruits ); // Apple, Orange, Pear
Les méthodes push et unshift peuvent ajouter plusieurs éléments à 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 dâobjet spĂ©cial. Les crochets utilisĂ©s pour accĂ©der Ă la propriĂ©tĂ© arr[0] proviennent en fait de la syntaxe de lâobjet. Câest essentiellement la mĂȘme chose que obj[key], oĂč arr est lâobjet, tandis que les nombres sont utilisĂ©s comme clĂ©s.
Ils Ă©tendent les objets en fournissant des mĂ©thodes spĂ©ciales pour travailler avec des collections ordonnĂ©es de donnĂ©es ainsi que la propriĂ©tĂ© length. Mais au fond câest toujours un objet.
Nâoubliez pas quâil nây a que huit types de base en JavaScript (voir le chapitre Les types de donnĂ©es pour plus dâinfos). Array est un objet et se comporte donc comme un objet.
Par exemple, il est copié par référence :
let fruits = ["Banana"]
let arr = fruits; // copier par rĂ©fĂ©rence (deux variables font rĂ©fĂ©rence au mĂȘme tableau)
alert( arr === fruits ); // true
arr.push("Pear"); // modifie le tableau par référence
alert( fruits ); // Banana, Pear - 2 items maintenant
âŠMais ce qui rend les tableaux vraiment spĂ©ciaux, câest leur reprĂ©sentation interne. Le moteur tente de stocker ses Ă©lĂ©ments dans une zone de mĂ©moire contiguĂ«, lâun aprĂšs lâautre, exactement comme le montrent les illustrations de ce chapitre. Il existe Ă©galement dâautres optimisations permettant de faire fonctionner les tableaux trĂšs rapidement.
Mais ils se cassent tous si nous arrĂȘtons de travailler avec un tableau comme avec une âcollection ordonnĂ©eâ et commençons Ă le travailler comme sâil sâagissait dâun objet normal.
Par exemple, techniquement, nous pouvons faire ceci :
let fruits = []; // créer un tableau
fruits[99999] = 5; // assigne une propriété avec un index beaucoup plus grand que sa longueur
fruits.age = 25; // créer une propriété avec un nom arbitraire
Câest possible, car les tableaux sont des objets Ă leur base. Nous pouvons leur ajouter des propriĂ©tĂ©s.
Mais le moteur verra que nous travaillons avec le tableau comme avec un objet normal. Les optimisations spécifiques à un tableau ne sont pas adaptées à ce type de situation et seront désactivées. Leurs avantages disparaissent.
Les moyens de casser un tableau :
- Ajouter une propriété non numérique comme
arr.test = 5. - Faire des trous, comme ajouter
arr[0]et ensuitearr[1000](et rien entre eux). - Remplire le tableau dans lâordre inverse, comme
arr[1000],arr[999]etc.
Veuillez considĂ©rer les tableaux comme des structures spĂ©ciales pour travailler avec les donnĂ©es ordonĂ©es. Ils fournissent des mĂ©thodes spĂ©ciales pour cela. Les tableaux sont soigneusement rĂ©glĂ©s dans les moteurs JavaScript pour fonctionner avec des donnĂ©es ordonnĂ©es contiguĂ«s, veuillez les utiliser de cette maniĂšre. Et si vous avez besoin de clĂ©s arbitraires, il y a de fortes chances pour que vous ayez rĂ©ellement besoin dâun objet rĂ©gulier {}.
Performance
Les méthodes push/pop vont vite, alors que shift/unshift sont lentes.
Pourquoi est-il plus rapide de travailler avec la fin dâun tableau quâavec son dĂ©but ? Voyons ce qui se passe pendant lâexĂ©cution :
fruits.shift(); // prends 1 élément du début
Il ne suffit pas de prendre lâĂ©lĂ©ment avec le nombre 0. Dâautres Ă©lĂ©ments doivent Ă©galement ĂȘtre renumĂ©rotĂ©s.
LâopĂ©ration shift doit faire 3 choses :
- Supprimer lâĂ©lĂ©ment avec lâindex
0. - DĂ©placer tous les Ă©lĂ©ments Ă gauche, les renumĂ©roter de lâindex
1Ă0, de2Ă1, etc. - Mettre Ă jour la propriĂ©tĂ©
length.
Plus il y a dâĂ©lĂ©ments dans le tableau, plus il y faut de temps pour les dĂ©placer, plus il y a dâopĂ©rations en mĂ©moire.
La mĂȘme chose se produit avec unshift. Pour ajouter un Ă©lĂ©ment au dĂ©but du tableau, nous devons dâabord dĂ©placer les Ă©lĂ©ments existants vers la droite, en augmentant leur index.
Et quâen est-il avec push/pop ? Ils nâont pas besoin de dĂ©placer quoi que ce soit. Pour extraire un Ă©lĂ©ment de la fin, la mĂ©thode pop nettoie lâindex et raccourcit length.
Les actions pour lâopĂ©ration pop :
fruits.pop(); // enleve 1 élément de la fin
La mĂ©thode pop nâa pas besoin de dĂ©placer quoi que ce soit, car les autres Ă©lĂ©ments conservent leurs index. Câest pourquoi câest extrĂȘmement rapide.
La mĂȘme chose avec la mĂ©thode push.
Boucles
Lâune des mĂ©thodes les plus anciennes pour cycler des Ă©lĂ©ments 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"];
// itÚre sur des éléments de tableau
for (let fruit of fruits) {
alert( fruit );
}
Le for..of ne donne pas accĂšs au numĂ©ro de lâĂ©lĂ©ment actuel, mais Ă sa valeur, mais dans la plupart des cas, cela suffit. Et câest plus court.
Techniquement, comme les tableaux sont des objets, il est Ă©galement possible dâutiliser for..in :
let arr = ["Apple", "Orange", "Pear"];
for (let key in arr) {
alert( arr[key] ); // Apple, Orange, Pear
}
Mais câest en fait une mauvaise idĂ©e. Il y a des problĂšmes potentiels avec cela :
-
La boucle
for..initĂšre sur toutes les propriĂ©tĂ©s, pas seulement les propriĂ©tĂ©s numĂ©riques.Il existe des objets dits âarray-likeâ dans le navigateur et dans dâautres environnements, qui ressemblent Ă des tableaux. Câest-Ă -dire quâils ont les propriĂ©tĂ©s
lengthet index, mais ils peuvent Ă©galement avoir dâautres propriĂ©tĂ©s et mĂ©thodes non numĂ©riques, dont nous nâavons gĂ©nĂ©ralement pas besoin. La bouclefor..inles listera cependant. Donc, si nous devons travailler avec des objets de type tableau, ces propriĂ©tĂ©s âsupplĂ©mentairesâ peuvent devenir un problĂšme. -
La boucle
for..inest optimisĂ©e pour les objets gĂ©nĂ©riques, pas pour les tableaux, elle est 10-100 fois plus lente. Bien sĂ»r, câest encore trĂšs rapide. LâaccĂ©lĂ©ration peut nâimporter que dans les goulots dâĂ©tranglement ou sembler hors de propos. Mais il faut quand mĂȘme ĂȘtre conscient de la diffĂ©rence.
En rÚgle générale, nous ne devrions pas utiliser for..in pour les tableaux.
Un mot Ă propos de âlengthâ
La propriĂ©tĂ© length est automatiquement mise Ă jour lorsque nous modifions le tableau. Pour ĂȘtre prĂ©cis, il ne sâagit pas du nombre de valeurs du tableau, mais du plus grand index numĂ©rique plus un.
Par exemple, un seul élément avec un grand index donne une grande longueur :
let fruits = [];
fruits[123] = "Apple";
alert( fruits.length ); // 124
Notez que nous nâutilisons gĂ©nĂ©ralement pas de tableaux de ce type.
Une autre chose intĂ©ressante Ă propos de la propriĂ©tĂ© length est quâelle est accessible en Ă©criture.
Si nous lâaugmentons manuellement, rien dâintĂ©ressant ne se produit. Mais si nous le diminuons, le tableau est tronquĂ©. Le processus est irrĂ©versible, voici lâexemple :
let arr = [1, 2, 3, 4, 5];
arr.length = 2; // tronque à 2 éléments
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 supplémentaire pour créer un tableau :
let arr = new Array("Apple", "Pear", "etc");
Il est rarement utilisé, car les crochets [] sont plus courts. En outre, il comporte une caractéristique délicate.
Si new Array est appelé avec un seul argument qui est un nombre, il crée un tableau sans éléments, mais avec la longueur donnée.
Voyons comment on peut se tirer une balle dans le pied :
let arr = new Array(2); // va-t-il créer un tableau de [2] ?
alert( arr[0] ); // undefined! pas d'éléments.
alert( arr.length ); // length 2
Pour éviter de telles surprises, nous utilisons généralement des crochets, sauf si nous savons vraiment ce que nous faisons.
Tableaux multidimensionnels
Les tableaux peuvent avoir des Ă©lĂ©ments qui sont aussi des tableaux. On peut lâutiliser 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'élément central
toString
Les tableaux ont leur propre implĂ©mentation de la mĂ©thode toString qui renvoie une liste dâĂ©lĂ©ments sĂ©parĂ©s 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 nâont pas de Symbol.toPrimitive, ni de valueOf viable, ils implĂ©mentent uniquement la conversion toString, donc ici [] devient une chaĂźne vide, [1] devient "1" et [1,2] devient "1,2".
Lorsque lâopĂ©rateur binaire plus + ajoute quelque chose Ă une chaĂźne, il la convertit Ă©galement en chaĂźne, de sorte que lâĂ©tape suivante se prĂ©sente 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 comparĂ©s avec lâopĂ©rateur ==.
Cet opĂ©rateur nâa pas de traitement spĂ©cial pour les tableaux, il fonctionne avec eux comme avec nâimporte quel objet.
Rappelons les rĂšgles :
- Deux objets sont égaux
==uniquement sâils font rĂ©fĂ©rence au mĂȘme objet. - Si lâun des arguments de
==est un objet, et lâautre est une primitive, alors lâobjet est converti en primitif, comme expliquĂ© dans le chapitre Conversion d'objet en primitive. - âŠĂ lâexception de
nulletundefinedqui sâĂ©galent==lâun lâautre et rien dâautre.
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 mĂȘmes, sauf si nous comparons deux variables qui rĂ©fĂ©rencent exactement le mĂȘme tableau.
Par exemple :
alert( [] == [] ); // false
alert( [0] == [0] ); // false
Ces tableaux sont des objets techniquement diffĂ©rents. Donc, ils ne sont pas Ă©gaux. LâopĂ©rateur == ne fait pas de comparaison Ă©lĂ©ment par Ă©lĂ©ment.
La comparaison avec les primitives peut également donner des résultats 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 chaĂźne vide ''.
Ensuite, le processus de comparaison se poursuit avec les primitives, comme décrit dans le chapitre Les conversions de types :
// aprĂšs que [] soit converti vers ''
alert( 0 == '' ); // true, car '' est converti en nombre 0
alert('0' == '' ); // false, pas de conversion de type, différentes chaßnes de caractÚres
Alors, comment comparer des tableaux ?
Câest simple, nâutilisez pas lâopĂ©rateur ==. Au lieu de cela, comparez-les Ă©lĂ©ment par Ă©lĂ©ment dans une boucle ou en utilisant les mĂ©thodes dâitĂ©ration expliquĂ©es dans le chapitre suivant.
Résumé
Array est un type dâobjet spĂ©cial, adaptĂ© au stockage et Ă la gestion des Ă©lĂ©ments de donnĂ©es ordonnĂ©es.
-
La déclaration :
// crochets (habituel) let arr = [item1, item2...]; // new Array (exceptionnellement rare) let arr = new Array(item1, item2...);Lâappel de
new Array(number)crée un tableau de longueur donnée, mais sans éléments. -
La propriété
lengthest la longueur du tableau ou, plus précisément, son dernier index numérique plus un. Il est auto-ajusté par les méthodes de tableau. -
Si nous raccourcissons
lengthmanuellement, le tableau est tronqué.
Obtenir les éléments :
- nous pouvons obtenir un élément par son index, comme
arr[0] - nous pouvons également utiliser la méthode
at(i)qui autorise les index négatifs. Pour les valeurs négatives dei, il recule à partir de la fin du tableau. Sii >= 0, cela fonctionne commearr[i].
Nous pouvons utiliser un tableau comme deque avec les opérations suivantes :
push(...items)ajouteitemsĂ la fin.pop()supprime lâĂ©lĂ©ment de la fin et le renvoie.shift()supprime lâĂ©lĂ©ment du dĂ©but et le renvoie.unshift(... items)ajoute desitemsau dĂ©but.
Pour boucler sur les éléments 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 Ă©lĂ©ments uniquement.pour (let i in arr)â ne jamais utiliser.
Pour comparer des tableaux, nâutilisez pas lâopĂ©rateur == (ainsi que >, < et autres), car ils nâont pas de traitement spĂ©cial pour les tableaux. Ils les traitent comme nâimporte quel objet, et ce nâest pas ce que nous voulons habituellement.
A la place, vous pouvez utiliser la boucle for..of pour comparer les tableaux élément par élément.
Nous continuerons avec les tableaux et Ă©tudierons dâautres mĂ©thodes pour ajouter, supprimer, extraire des Ă©lĂ©ments et trier des tableaux dans le prochain chapitre MĂ©thodes de tableau.
Commentaires
<code>, pour plusieurs lignes â enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepenâŠ)