De nombreuses fonctions JavaScript intégrées prennent en charge un nombre arbitraire d'arguments.
Par exemple:
Math.max(arg1, arg2, ..., argN)
– renvoie le plus grand des arguments.
Object.assign(dest, src1, ..., srcN)
– copie les propriétés de src1..N
dans dest
.
…et ainsi de suite.
Dans ce chapitre, nous apprendrons comment faire de même. Et aussi, comment transmettre des tableaux à des fonctions telles que des paramètres.
...
Une fonction peut être appelée avec n'importe quel nombre d'arguments, quelle que soit la manière dont elle est définie.
Comme ici :
fonction somme(a, b) { renvoyer a + b ; } alerte( somme(1, 2, 3, 4, 5) );
Il n’y aura pas d’erreur à cause d’arguments « excessifs ». Mais bien sûr dans le résultat seuls les deux premiers seront comptés, donc le résultat dans le code ci-dessus est 3
.
Le reste des paramètres peut être inclus dans la définition de la fonction en utilisant trois points ...
suivis du nom du tableau qui les contiendra. Les points signifient littéralement « rassembler les paramètres restants dans un tableau ».
Par exemple, pour rassembler tous les arguments dans un tableau args
:
function sumAll(...args) { // args est le nom du tableau soit somme = 0 ; pour (laisser argument des arguments) sum += arg; retourner la somme ; } alerte( sumAll(1) ); // 1 alerte( sumAll(1, 2) ); // 3 alerte( sumAll(1, 2, 3) ); // 6
Nous pouvons choisir d'obtenir les premiers paramètres sous forme de variables et de collecter uniquement le reste.
Ici, les deux premiers arguments vont dans les variables et le reste dans le tableau titles
:
function showName (prénom, nom, ... titres) { alert( prénom + ' ' + nom de famille ); // Jules César // le reste va dans le tableau des titres // c'est à dire titres = ["Consul", "Imperator"] alerte( titres[0] ); // Consul alerte( titres[1] ); // Imperateur alert( titres.longueur ); // 2 } showName("Jules", "César", "Consul", "Imperator");
Les autres paramètres doivent être à la fin
Les paramètres rest rassemblent tous les arguments restants, donc ce qui suit n'a pas de sens et provoque une erreur :
function f(arg1, ...rest, arg2) { // arg2 après ...rest ?! // erreur }
Le ...rest
doit toujours être le dernier.
Il existe également un objet spécial de type tableau nommé arguments
qui contient tous les arguments par leur index.
Par exemple:
fonction showName() { alert( arguments.length ); alerte( arguments[0] ); alerte( arguments[1] ); // c'est itérable // for(laisser l'argument des arguments) alert(arg); } // spectacles : 2, Jules, César showName("Jules", "César"); // affiche : 1, Ilya, non défini (pas de deuxième argument) showName("Ilya");
Autrefois, les paramètres de repos n'existaient pas dans le langage et l'utilisation arguments
était le seul moyen d'obtenir tous les arguments de la fonction. Et ça marche toujours, on le retrouve dans l’ancien code.
Mais l’inconvénient est que même si arguments
ressemblent à un tableau et sont itérables, ce n’est pas un tableau. Il ne prend pas en charge les méthodes de tableau, nous ne pouvons donc pas appeler arguments.map(...)
par exemple.
De plus, il contient toujours tous les arguments. Nous ne pouvons pas les capturer partiellement, comme nous l'avons fait avec les paramètres de repos.
Ainsi, lorsque nous avons besoin de ces fonctionnalités, les paramètres de repos sont préférés.
Les fonctions fléchées n'ont pas "arguments"
Si nous accédons à l’objet arguments
à partir d’une fonction fléchée, cela les prend à partir de la fonction « normale » externe.
Voici un exemple :
fonction f() { let showArg = () => alert(arguments[0]); showArg(); } f(1); // 1
Comme nous nous en souvenons, les fonctions fléchées n'ont pas leur propre this
. Maintenant, nous savons qu'ils n'ont pas non plus d'objet arguments
spéciaux.
Nous venons de voir comment récupérer un tableau à partir de la liste des paramètres.
Mais parfois, nous devons faire exactement l’inverse.
Par exemple, il existe une fonction intégrée Math.max qui renvoie le plus grand nombre d'une liste :
alerte( Math.max(3, 5, 1) ); // 5
Disons maintenant que nous avons un tableau [3, 5, 1]
. Comment appelle-t-on Math.max
avec ?
Le transmettre « tel quel » ne fonctionnera pas, car Math.max
attend une liste d'arguments numériques, pas un seul tableau :
soit arr = [3, 5, 1]; alerte( Math.max(arr) ); // NaN
Et nous ne pouvons sûrement pas lister manuellement les éléments dans le code Math.max(arr[0], arr[1], arr[2])
, car nous ne savons peut-être pas combien il y en a. Au fur et à mesure de l'exécution de notre script, il peut y en avoir beaucoup, ou il peut y en avoir aucun. Et ça deviendrait moche.
Diffusez la syntaxe à la rescousse ! Cela ressemble aux paramètres de repos, utilisant également ...
, mais fait tout le contraire.
Lorsque ...arr
est utilisé dans l'appel de fonction, il « développe » un objet itérable arr
dans la liste d'arguments.
Pour Math.max
:
soit arr = [3, 5, 1]; alert( Math.max(...arr) ); // 5 (spread transforme le tableau en une liste d'arguments)
Nous pouvons également transmettre plusieurs itérables de cette façon :
soit arr1 = [1, -2, 3, 4] ; soit arr2 = [8, 3, -8, 1] ; alerte( Math.max(...arr1, ...arr2) ); // 8
Nous pouvons même combiner la syntaxe spread avec des valeurs normales :
soit arr1 = [1, -2, 3, 4] ; soit arr2 = [8, 3, -8, 1] ; alerte( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25
De plus, la syntaxe spread peut être utilisée pour fusionner des tableaux :
soit arr = [3, 5, 1]; soit arr2 = [8, 9, 15] ; soit fusionné = [0, ...arr, 2, ...arr2]; alerte (fusionnée); // 0,3,5,1,2,8,9,15 (0, puis arr, puis 2, puis arr2)
Dans les exemples ci-dessus, nous avons utilisé un tableau pour démontrer la syntaxe de propagation, mais n'importe quel itérable fera l'affaire.
Par exemple, nous utilisons ici la syntaxe spread pour transformer la chaîne en tableau de caractères :
let str = "Bonjour"; alerte( [...str] ); // Bonjour
La syntaxe spread utilise en interne des itérateurs pour rassembler des éléments, de la même manière que for..of
.
Ainsi, pour une chaîne, for..of
renvoie des caractères et ...str
devient "H","e","l","l","o"
. La liste des caractères est transmise à l'initialiseur de tableau [...str]
.
Pour cette tâche particulière, nous pourrions également utiliser Array.from
, car il convertit un itérable (comme une chaîne) en tableau :
let str = "Bonjour"; // Array.from convertit un itérable en tableau alert( Array.from(str) ); // Bonjour
Le résultat est le même que [...str]
.
Mais il y a une différence subtile entre Array.from(obj)
et [...obj]
:
Array.from
fonctionne à la fois sur les tableaux et les itérables.
La syntaxe spread ne fonctionne qu'avec les itérables.
Ainsi, pour la tâche consistant à transformer quelque chose en tableau, Array.from
a tendance à être plus universel.
Vous vous souvenez quand nous avons parlé d' Object.assign()
dans le passé ?
Il est possible de faire la même chose avec la syntaxe spread.
soit arr = [1, 2, 3]; laissez arrCopy = [...arr]; // répartit le tableau en une liste de paramètres // puis met le résultat dans un nouveau tableau // les tableaux ont-ils le même contenu ? alert(JSON.stringify(arr) === JSON.stringify(arrCopy)); // vrai // les tableaux sont-ils égaux ? alert(arr === arrCopie); // faux (pas la même référence) // modifier notre tableau initial ne modifie pas la copie : arr.push(4); alerte(arr); // 1, 2, 3, 4 alert(arrCopie); // 1, 2, 3
A noter qu'il est possible de faire la même chose pour faire une copie d'un objet :
soit obj = { a : 1, b : 2, c : 3 } ; laissez objCopy = { ...obj }; // répartit l'objet dans une liste de paramètres // puis renvoie le résultat dans un nouvel objet // les objets ont-ils le même contenu ? alert(JSON.stringify(obj) === JSON.stringify(objCopy)); // vrai // les objets sont-ils égaux ? alerte(obj === objCopy); // faux (pas la même référence) // modifier notre objet initial ne modifie pas la copie : obj.d = 4 ; alerte(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4} alerte(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3}
Cette façon de copier un objet est beaucoup plus courte que let objCopy = Object.assign({}, obj)
ou pour un tableau let arrCopy = Object.assign([], arr)
donc nous préférons l'utiliser chaque fois que nous le pouvons.
Quand on voit "..."
dans le code, il s'agit soit des paramètres de repos, soit de la syntaxe spread.
Il existe un moyen simple de les distinguer :
Lorsque ...
est à la fin des paramètres de la fonction, il s'agit de « paramètres de repos » et rassemble le reste de la liste des arguments dans un tableau.
Lorsque ...
se produit dans un appel de fonction ou similaire, cela s'appelle une « syntaxe étalée » et développe un tableau en une liste.
Utiliser des modèles :
Les paramètres de repos sont utilisés pour créer des fonctions qui acceptent n'importe quel nombre d'arguments.
La syntaxe spread est utilisée pour transmettre un tableau à des fonctions qui nécessitent normalement une liste de nombreux arguments.
Ensemble, ils permettent de naviguer facilement entre une liste et un ensemble de paramètres.
Tous les arguments d'un appel de fonction sont également disponibles dans arguments
« à l'ancienne » : objet itérable de type tableau.