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â¦)