Une fonction déclare deux paramètres, on lui en passe cinq. Que deviennent les trois autres ? Ils ne disparaissent pas : ils sont rangés dans un objet automatique, présent dans toute fonction classique sans qu'on ait à le demander.
Définition
arguments est un objet créé par le moteur à chaque appel d'une fonction déclarée avec le mot-clé function. Il contient toutes les valeurs reçues, dans l'ordre, y compris celles qui ne correspondent à aucun paramètre déclaré.
function total() {
console.log(arguments.length); // 3
console.log(arguments[0]); // 5
return Array.from(arguments).reduce((a, b) => a + b, 0);
}
console.log(total(5, 10, 15)); // 30La fonction ne déclare aucun paramètre et travaille pourtant sur trois valeurs. C'était la seule façon d'écrire une fonction à nombre d'arguments variable avant 2015.
Un objet qui imite un tableau sans en être un
C'est la source d'erreur numéro un. L'objet possède un length et des indices numériques, ce qui suffit à donner l'illusion, mais il n'hérite d'aucune méthode de tableau.
| Écriture | Résultat |
|---|---|
arguments.length | Fonctionne |
arguments[0] | Fonctionne |
Array (tableau).isArray(arguments) | false |
arguments.map(...) | Erreur, la méthode n'existe pas |
Pour en faire un vrai tableau, une seule ligne suffit : Array.from(arguments), ou [...arguments] avec le Spread (...). Les deux produisent le même résultat.
Une fonction fléchée n'a pas d'objet arguments à elle. Elle utilise celui de la fonction qui l'entoure, et s'il n'y en a pas, la lecture échoue sur une erreur de référence. C'est voulu : la flèche n'a été conçue ni pour this, ni pour arguments.
Ce qui l'a remplacé
Depuis 2015, le paramètre du Rest (...) fait le même travail en mieux. Il donne un vrai tableau, il porte un nom explicite, et il fonctionne dans les fonctions fléchées.
// Écriture ancienne
function ancienne() {
return Array.from(arguments).join(", ");
}
// Écriture actuelle, plus lisible
const moderne = (...valeurs) => valeurs.join(", ");
console.log(moderne("a", "b")); // "a, b"Il reste une raison d'en connaître le fonctionnement : le code existant. Une base de code écrite avant 2015 en est remplie, et savoir le lire évite de réécrire à l'aveugle.
Questions fréquentes
Pourquoi arguments.map ne fonctionne-t-il pas ?
Parce que ce n'est pas un tableau, seulement un objet qui lui ressemble. Aucune méthode de tableau n'y est disponible. Convertissez-le d'abord avec Array.from(arguments), puis enchaînez normalement les méthodes qui vous intéressent.
Faut-il encore l'utiliser dans du code neuf ?
Non. Le paramètre du Rest (...) le remplace intégralement, avec un nom parlant et un vrai tableau à la clé. Certains outils d'analyse le signalent d'ailleurs comme une écriture dépassée. Gardez-le uniquement pour comprendre du code ancien.
Que contient-il si un paramètre a une valeur par défaut ?
Uniquement ce qui a réellement été transmis à l'appel, jamais les valeurs par défaut. Une fonction avec un paramètre par défaut, appelée sans argument, verra arguments.length à zéro alors que le paramètre, lui, porte bien sa valeur. Les deux ne décrivent pas la même chose.