Paramètres vs arguments en JavaScript
Voilà deux mots qu'on confond tout le temps. Un paramètre, c'est le nom déclaré dans la définition de la fonction. Un argument, c'est la valeur que tu passes au moment de l'appel. Le principe est exactement le même qu'en Python ou dans la plupart des autres langages :
a et b sont des paramètres. 2 et 3 sont des arguments. JavaScript les associe par position : le premier argument va au premier paramètre, et ainsi de suite. La nuance est subtile, mais c'est le vocabulaire utilisé par les messages d'erreur et la doc MDN.
JavaScript et son rapport très souple à l'arité
Contrairement à beaucoup d'autres langages, JavaScript se moque pas mal du nombre d'arguments que vous passez. S'il en manque, les paramètres concernés valent undefined. S'il y en a trop, ils sont tout simplement ignorés :
Le premier appel affiche Bonjour, Ada undefined — last n'a reçu aucune valeur, donc il vaut undefined, et les template literals l'interpolent sans broncher. Aucune erreur, aucun avertissement. Cette souplesse est parfois pratique, parfois source de bugs — et c'est précisément pour ça que les paramètres par défaut existent.
Définir une valeur par défaut
Il suffit d'ajouter = suivi d'une valeur après le nom du paramètre. Si l'appelant ne fournit pas l'argument (ou passe undefined), la valeur par défaut prend le relais :
Les trois appels fonctionnent. Le premier et le troisième déclenchent la valeur par défaut, tandis que le deuxième utilise celle qu'on a passée. C'est la syntaxe ES6 — avant 2015, il fallait écrire name = name || "friend" dans le corps de la fonction, ce qui posait problème avec les valeurs falsy comme 0 ou "".
Un paramètre par défaut peut être n'importe quelle expression, pas seulement une valeur littérale :
L'expression est évaluée à chaque appel, pas une seule fois au moment de la définition de la fonction. Du coup, pas de piège des valeurs par défaut mutables comme en Python — chaque appel récupère un new Date() tout frais.
Seul undefined déclenche la valeur par défaut
Voilà la règle qui surprend tout le monde. Les paramètres par défaut se déclenchent quand l'argument vaut undefined, pas quand il est falsy, et surtout pas quand il vaut null :
Seul le dernier appel utilise "friend". Quand tu passes null explicitement, tu dis à JavaScript « la valeur est null » — et il te prend au mot. Pareil pour les chaînes vides et les zéros : ce sont des valeurs à part entière, pas des arguments manquants.
Si tu veux traiter null comme un argument absent, il faut gérer le cas toi-même :
L'opérateur ?? (coalescence des nuls) considère à la fois null et undefined comme des valeurs « absentes ». On y reviendra plus en détail dans un chapitre ultérieur.
Un paramètre par défaut basé sur un autre paramètre
Les paramètres sont évalués de la gauche vers la droite, ce qui veut dire qu'une valeur par défaut peut réutiliser n'importe quel paramètre déclaré avant elle :
Passer un seul argument, et on obtient un cube. Deux arguments, et c'est un prisme à base carrée. Attention à l'ordre de déclaration : impossible de faire référence à un paramètre qui n'a pas encore été déclaré :
function bad(a = b, b = 1) {
return a + b;
}
bad(); // ReferenceError: Cannot access 'b' before initialization
Mêmes règles qu'avec les variables déclarées avec let : les utiliser avant de les déclarer génère une erreur.
Valeurs par défaut et destructuration
On peut destructurer les paramètres et leur attribuer des valeurs par défaut en même temps. C'est un pattern très courant quand une fonction reçoit un « objet d'options » en argument :
Deux niveaux de valeurs par défaut sont à l'œuvre ici. Les plus internes (role = "member", active = true) comblent les propriétés manquantes. Le = {} externe, lui, gère le cas où l'appelant ne passe aucun argument — sans lui, createUser() tenterait de déstructurer undefined et lèverait une erreur.
Le motif paraît touffu au premier coup d'œil, mais on le croise partout dans le JavaScript moderne. Une fois que l'œil reconnaît { ... } = {} comme « un objet d'options avec des valeurs par défaut », la lecture devient fluide.
Sauter un argument au milieu
JavaScript n'a pas les arguments nommés à la Python. Pour sauter un paramètre intermédiaire et utiliser sa valeur par défaut, il faut passer explicitement undefined :
Passer undefined pour prefix permet de conserver la valeur par défaut. C'est moche. Si vous vous retrouvez à écrire undefined dans vos appels à répétition, c'est le signe qu'il faut passer à un objet d'options :
Maintenant, c'est l'appelant qui précise ce qu'il veut remplacer, et l'ordre n'a plus d'importance.
Les valeurs par défaut ne comptent pas dans length
Un petit détail qui passe souvent inaperçu, mais qui peut surprendre. La propriété length d'une fonction renvoie le nombre de paramètres situés avant le premier paramètre doté d'une valeur par défaut :
Certaines bibliothèques qui inspectent les fonctions (comme des outils de test ou d'injection de dépendances) se servent de length pour compter les paramètres « requis ». C'est bon à savoir, mais pas la peine de le retenir par cœur — sauf si tu développes ce genre d'outil.
La suite : rest et spread
Les valeurs par défaut règlent le cas où tu connais les paramètres à l'avance. Mais parfois, ce n'est pas le cas : tu veux qu'une fonction accepte un nombre quelconque d'arguments, ou qu'elle transmette tout un lot d'arguments à une autre fonction. C'est exactement le rôle de ...rest et de l'opérateur spread, qu'on va voir juste après.
Questions fréquentes
Comment définir une valeur par défaut pour un paramètre en JavaScript ?
Il suffit d'ajouter = suivi de la valeur par défaut après le nom du paramètre dans la signature de la fonction : function greet(name = 'ami') { ... }. Si l'appelant ne passe rien (ou passe explicitement undefined), c'est la valeur par défaut qui est utilisée. Cette syntaxe vient d'ES6 et fonctionne dans tous les environnements JavaScript modernes.
Quelle est la différence entre paramètres et arguments ?
Les paramètres sont les noms déclarés dans la définition de la fonction — dans function add(a, b), a et b sont les paramètres. Les arguments sont les valeurs réellement passées lors de l'appel — dans add(2, 3), les arguments sont 2 et 3. La nuance est utile pour bien comprendre les messages d'erreur et la documentation.
La valeur par défaut s'applique-t-elle si je passe null ?
Non. La valeur par défaut ne se déclenche que si l'argument vaut undefined (ou s'il est totalement absent). Passer explicitement null revient à dire « je te donne une valeur, et cette valeur, c'est null » — le défaut est donc ignoré. C'est un piège classique quand on vient d'un langage où null et undefined sont traités de la même manière.
Une valeur par défaut peut-elle référencer un autre paramètre ?
Oui. Les paramètres sont évalués de gauche à droite, donc un paramètre peut réutiliser la valeur de ceux qui le précèdent : function box(width, height = width). Vous pouvez aussi appeler une fonction dans la valeur par défaut — par exemple function log(msg, time = Date.now()) — et l'expression sera réévaluée à chaque appel.