Menu
Français

Spread et Rest en JavaScript : l'opérateur ...

Comment fonctionne l'opérateur ... en JavaScript : récupérer des arguments avec rest, étaler des tableaux et objets avec spread, et savoir quand utiliser l'un ou l'autre.

Une seule syntaxe, deux rôles opposés

Les trois petits points ... reviennent sans arrêt en JavaScript moderne, et selon l'endroit où on les place, ils font deux choses exactement inverses. Une fois qu'on a repéré la logique, toute utilisation de l'opérateur ... en JavaScript rentre dans l'une de ces deux cases :

  • Rest : ...nom côté réception regroupe plusieurs valeurs dans un seul tableau ou objet.
  • Spread : ...valeur côté envoi éclate un tableau ou un objet en ses éléments individuels.

C'est tout le modèle mental à retenir. Le reste de cette page, ce sont juste des exemples concrets de chacun, et les patterns que tu vas réutiliser en boucle.

Les paramètres rest en JavaScript : regrouper les arguments

Un paramètre rest dans la signature d'une fonction collecte n'importe quel nombre d'arguments dans un vrai tableau :

index.js
Output
Click Run to see the output here.

nums est un tableau tout ce qu'il y a de plus classique. Tu peux le passer à .map, à .filter, regarder sa .length, le transmettre à une autre fonction — bref, tout ce qu'on fait d'habitude avec un tableau.

Les paramètres rest peuvent cohabiter avec des paramètres classiques, à condition que le paramètre rest soit toujours en dernière position :

index.js
Output
Click Run to see the output here.

label capte le premier argument ; tout ce qui suit atterrit dans items. Placer le paramètre rest ailleurs qu'en dernière position déclenche une erreur de syntaxe.

Rest vs l'ancien objet arguments

L'ancien code JavaScript s'appuie sur une variable un peu magique appelée arguments, disponible dans les fonctions classiques. Elle ressemble à un tableau, mais n'en est pas vraiment un : impossible donc d'y appliquer directement les méthodes de tableau. Les paramètres rest la remplacent sans effort :

index.js
Output
Click Run to see the output here.

Les fonctions fléchées n'ont même pas d'objet arguments : les paramètres rest sont donc le seul moyen d'y accepter un nombre variable d'arguments. Dans tout nouveau code, privilégie ...args.

L'opérateur spread dans les appels de fonction

Le spread fait exactement l'inverse : il prend un tableau et le décompose en arguments individuels au moment de l'appel.

index.js
Output
Click Run to see the output here.

Math.max attend des nombres individuels, pas un tableau. Avant le spread, il fallait écrire Math.max.apply(null, nums). Aujourd'hui, un simple ... suffit.

Remarquez bien : le même ... joue le rôle de rest dans la définition de la fonction et de spread dans l'appel — c'est sa position qui détermine son rôle.

Spread dans les littéraux de tableau

L'opérateur spread dans un littéral de tableau permet de copier ou de combiner des tableaux :

index.js
Output
Click Run to see the output here.

[...a] te donne un nouveau tableau avec les mêmes éléments — pratique quand tu veux trier ou modifier sans toucher à l'original :

index.js
Output
Click Run to see the output here.

scores reste intact puisque .sort s'est appliqué sur la copie. Petit réflexe, mais gros bénéfice quand tu écris du code qui ne doit pas provoquer d'effets de bord inattendus.

L'opérateur spread sur les objets en JavaScript

L'opérateur spread fonctionne aussi sur les objets classiques : il fusionne leurs propriétés dans un nouvel objet.

index.js
Output
Click Run to see the output here.

Ce sont les dernières clés qui l'emportent. updates.age écrase user.age, et city s'ajoute au passage. L'ordre des spreads détermine le résultat final — gardez bien ça en tête quand vous empilez des valeurs par défaut et des surcharges :

index.js
Output
Click Run to see the output here.

Les valeurs par défaut d'abord, les choix de l'utilisateur ensuite. C'est fontSize de l'utilisateur qui l'emporte, tandis que theme est hérité.

Le piège de la copie superficielle

L'opérateur spread copie sur un seul niveau. Les objets et tableaux imbriqués restent partagés entre l'original et la copie :

index.js
Output
Click Run to see the output here.

Les deux tableaux affichent le nouveau tag parce que copy.tags et original.tags pointent vers le même tableau. Le spread n'a pas cloné la liste imbriquée — il a juste recopié la référence.

Pour obtenir une vraie copie profonde de données simples, utilise plutôt structuredClone :

index.js
Output
Click Run to see the output here.

Les deux tableaux sont désormais indépendants. structuredClone est disponible nativement dans les navigateurs modernes et dans Node, gère les structures imbriquées, et c'est la bonne solution dès que le clonage superficiel ne suffit plus.

Les paramètres rest dans la déstructuration

L'opérateur rest fonctionne aussi en déstructuration : il récupère tous les éléments ou propriétés restants.

index.js
Output
Click Run to see the output here.

Extraire quelques champs et regrouper le reste dans un seul objet : c'est un grand classique quand on transmet des props, qu'on retire des champs sensibles ou qu'on prépare une version modifiée de données :

index.js
Output
Click Run to see the output here.

password est extrait (puis ignoré) ; safe récupère tout le reste. Aucune mutation, aucune copie manuelle.

Récapitulatif rapide

  • ...nom dans une liste de paramètres ou un pattern de destructuration, c'est rest : ça collecte.
  • ...valeur dans un appel de fonction, un littéral de tableau ou un littéral d'objet, c'est spread : ça étale.
  • Les copies avec spread sont superficielles. Les structures imbriquées restent partagées. Pour une copie en profondeur, passe par structuredClone.
  • Les paramètres rest sont de vrais tableaux — utilise-les à la place de arguments.
  • Dans un littéral d'objet, les spreads placés plus loin écrasent ceux d'avant : c'est comme ça qu'on construit un système de valeurs par défaut avec surcharge.

La suite : les closures

En JavaScript, les fonctions ne se contentent pas de prendre des arguments et de renvoyer un résultat — elles mémorisent aussi la portée dans laquelle elles ont été définies. Cette mémoire s'appelle une closure, et c'est le mécanisme qui se cache derrière les callbacks, les factories et la plupart des patterns que tu vas croiser dans la page suivante.

Questions fréquentes

Quelle est la différence entre rest et spread en JavaScript ?

Les deux utilisent la même syntaxe ... mais font exactement l'inverse. Rest regroupe plusieurs valeurs dans un seul tableau — on le retrouve dans la liste des paramètres d'une fonction et dans la déstructuration. Spread étale un itérable ou un objet en ses éléments — on le retrouve dans les appels de fonctions, les tableaux et les objets littéraux. Retiens cette règle : si ... est du côté qui reçoit, c'est rest ; s'il est du côté qui donne, c'est spread.

Comment fonctionnent les paramètres rest dans une fonction ?

Un paramètre rest comme function sum(...nums) regroupe tous les arguments passés à la fonction dans un vrai tableau appelé nums. Il doit obligatoirement être le dernier paramètre de la liste. Contrairement à l'ancien objet arguments, un paramètre rest est un vrai Array, donc .map, .filter et .reduce fonctionnent directement dessus, sans bidouillage.

L'opérateur spread fait-il une copie profonde ?

Non. Spread ne copie qu'un seul niveau — c'est une copie superficielle (shallow copy). { ...user } te donne un nouvel objet avec les mêmes clés de premier niveau, mais les objets et tableaux imbriqués restent des références partagées. Pour une copie profonde, utilise structuredClone(value), ou passe par JSON.parse(JSON.stringify(...)) pour des données simples.

Apprendre à coder avec Coddy

COMMENCER