JS protip : Array.from() ou Array#fill() ?
Par Christophe Porteneuve • Publié le 22 mars 2023
• 3 min
This page is also available in English.
Je vois régulièrement ces temps-ci des gens copier/coller ce petit bout de code pour produire un tableau de N copies d’une même valeur :
Array.from({ length: 10 }).fill(42)
// => [42, 42, 42, 42, 42, 42, 42, 42, 42, 42]
C’est inutilement verbeux pour le coup, mais ça ne veut pas dire que from()
est inutile, loin de là ! Comment bien choisir‚ alors ?
Toujours la même valeur : faisons court avec juste fill()
JavaScript a toujours permis d’initialiser un tableau à une longueur donnée avec Array(n)
. C’est hyper concis, mais les cellules du tableau n’existent pas, c’est un peu le tableau clairsemé ultime : il n’a aucune cellule définie !
Du coup les opérations type map()
et consorts ne feraient rien, ou renverraient leur résultat par défaut, « à vide » :
Array(10)
// => [ , , , , , , , , , ] -- 10 positions, mais non définies
Array(10).map((n) => n * 2)[2]
// => undefined. Aucune cellule n'est exploitée
Array(10).every(() => false)
// => true (par défaut : aucune cellule n'est examinée)
Array(10).some(() => true)
// => false (par défaut : idem, aucun examen)
La façon classique de « remplir » le tableau consiste à utiliser fill()
sur celui-ci :
Array(10).fill(42)
// => [ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 ]
C’est super quand la valeur est toujours la même (par exemple false
, 0
ou la chaîne vide ''
), ce qui arrive tout de même régulièrement en pratique, au début d’un traitement le plus souvent.
Mais quand la valeur change d’une cellule à l’autre ?
Valeurs distinctes : utilisons intelligement from()
À la base, Array.from()
sert principalement à convertir un itérable en véritable Array
. Par exemple à partir d’une Map
, d’un Set
, des codepoints d’une String
ou encore d’une NodeList
, pour citer les cas les plus courants.
En pratique, si l’argument n’est pas itérable, il doit au moins être “array-like”, c’est-à-dire exploitable par les méthodes standard de Array
, et donc disposer d’une propriété length
qui soit un entier positif (ou nul).
Pour l’anecdote d’ailleurs, Array.from({ length: 5 })
n’est pas tout-à-fait la même chose que Array(5)
: le second ne définit pas les cellules, alors que le premier les cale à undefined
:
Array(5)
// => [ , , , , ]
2 in Array(5)
// => false (par de propriété [2] définie)
Array.from({ length: 5 })
// => [ undefined, undefined, undefined, undefined, undefined ]
2 in Array.from({ length: 5 })
// => true
C’est cool, mais le vrai bonus est son deuxième argument, optionnel : le mapper, la fonction de transformation à la volée.
On peut s’en servir pour générer des valeurs quelconques, ou les baser sur la position par exemple, puisque comme la plupart des méthodes itératives (par exemple map()
ou filter()
), elle reçoit non seulement la valeur de base, mais aussi son index.
Array.from({ length: 10 }, (n, i) => i + 1)
// => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
Array.from({ length: 5 }, () => Math.round(Math.random() * 100))
// => [ 65, 4, 62, 31, 73 ]
Pourquoi pas une fonction range()
, façon Lodash (la borne end
est exclusive / ouverte) ?
function range(start = 0, end, step = 1) {
if (end === undefined) {
;[start, end] = [0, start]
}
const length = Math.ceil((end - start) / step)
return Array.from({ length }, (u, index) => start + index * step)
}
range(5)
// => [ 0, 1, 2, 3, 4 ]
range(1, 5)
// => [ 1, 2, 3, 4 ]
range(1, 10, 2)
// => [ 1, 3, 5, 7, 9 ]
range(-1, -10, -2)
// => [ -1, -3, -5, -7, -9 ]
Sympa 😎
TL;PL
from()
part d’une source et peut calculer les valeurs à la voléefill()
est plus pratique pour une valeur unique, et plus concise avecArray(size)
- Les deux datent de ES2015 (donc dispo partout sauf IE, mais désormais on s’en fiche complètement)
Références
Les docs interactives en français du MDN sont comme toujours super utiles :
Des astuces en veux-tu en voilà !
On a tout plein d’articles et de vidéos existants et encore beaucoup à venir. Pour ne rien manquer, tu devrais penser à t’abonner à notre newsletter, à notre chaîne YouTube, nous suivre sur Twitter ou encore mieux, à suivre une de nos formations du feu de dieu 🔥 !