14
Spread & Rest
L'opérateur ... (trois points)
L'opérateur ... est l'un des ajouts les plus puissants d'ES6. Il a deux rôles opposés selon
le contexte : Spread (expansion) et Rest (collecte).
🔄 Spread vs Rest : Même syntaxe, contextes opposés
SPREAD
Expansion (Donner)
Décompose un iterable en éléments individuels.
const arr = [1, 2, 3];
console.log(...arr); // 1 2 3
const obj = { a: 1, b: 2 };
const copy = { ...obj }; // Clone
Contextes : Arguments de fonction, tableaux, objets
REST
Collecte (Recevoir)
Rassemble plusieurs éléments en un tableau.
function sum(...numbers) {
return numbers.reduce((a, b) => a + b);
}
sum(1, 2, 3); // numbers = [1,2,3]
Contextes : Paramètres de fonction, destructuring
📤 Patterns Spread (Expansion)
// 1. SPREAD DANS LES TABLEAUX
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
// Concaténation
const combined = [...arr1, ...arr2]; // [1,2,3,4,5,6]
// Insertion au milieu
const inserted = [...arr1, 99, ...arr2]; // [1,2,3,99,4,5,6]
// Clone superficiel
const clone = [...arr1]; // Nouveau tableau
// 2. SPREAD DANS LES OBJETS
const user = { name: 'Alice', age: 25 };
const location = { city: 'Paris', country: 'France' };
// Fusion d'objets
const profile = { ...user, ...location };
// { name: 'Alice', age: 25, city: 'Paris', country: 'France' }
// Override de propriétés (ordre important !)
const updated = { ...user, age: 26 }; // age écrasé
const wrong = { age: 26, ...user }; // age de user gagne
// 3. SPREAD DANS LES APPELS DE FONCTION
const numbers = [5, 2, 8, 1];
Math.max(...numbers); // 8 (au lieu de Math.max(5,2,8,1))
// Équivalent à :
Math.max.apply(null, numbers); // Ancienne méthode
📥 Patterns Rest (Collecte)
// 1. REST DANS LES PARAMÈTRES
function logAll(...args) {
console.log('Nombre d\'args:', args.length);
args.forEach(arg => console.log(arg));
}
logAll('a', 'b', 'c'); // args = ['a', 'b', 'c']
// Combiné avec paramètres normaux (rest DOIT être dernier)
function greet(greeting, ...names) {
return `${greeting} ${names.join(', ')}`;
}
greet('Hello', 'Alice', 'Bob'); // "Hello Alice, Bob"
// 2. REST DANS LE DESTRUCTURING (Arrays)
const [first, second, ...others] = [1, 2, 3, 4, 5];
// first = 1, second = 2, others = [3, 4, 5]
const [head, ...tail] = [10, 20, 30];
// head = 10, tail = [20, 30]
// 3. REST DANS LE DESTRUCTURING (Objects)
const person = { name: 'Bob', age: 30, city: 'Lyon', job: 'Dev' };
const { name, age, ...rest } = person;
// name = 'Bob', age = 30, rest = { city: 'Lyon', job: 'Dev' }
// Utile pour extraire certaines props
const { password, ...publicData } = userFromDB;
// Retire password, garde le reste
🎮 Visualiseur Spread/Rest
Testez différents patterns et voyez le résultat.
Cliquez sur un bouton pour voir la démo
💼 Cas d'Usage Pratiques
// 1. CLONER ET MODIFIER UN OBJET (Immutabilité)
const originalState = { count: 0, user: 'Alice' };
const newState = { ...originalState, count: 1 };
// originalState inchangé, newState = { count: 1, user: 'Alice' }
// 2. AJOUTER UN ÉLÉMENT À UN TABLEAU (Immutable)
const todos = ['Task 1', 'Task 2'];
const newTodos = [...todos, 'Task 3']; // Pas de .push()
// 3. RETIRER UNE PROPRIÉTÉ D'UN OBJET
const { password, ...safeUser } = user;
// safeUser n'a plus password
// 4. FUSIONNER DES CONFIGS
const defaultConfig = { theme: 'dark', lang: 'fr', timeout: 5000 };
const userConfig = { lang: 'en', timeout: 3000 };
const finalConfig = { ...defaultConfig, ...userConfig };
// { theme: 'dark', lang: 'en', timeout: 3000 }
// 5. FONCTION VARIADIC (nombre variable d'args)
function createURL(base, ...segments) {
return base + '/' + segments.join('/');
}
createURL('https://api.com', 'users', '123', 'posts');
// "https://api.com/users/123/posts"
// 6. CONVERTIR ARGUMENTS EN ARRAY
function oldStyle() {
const args = [...arguments]; // arguments n'est pas un vrai array
return args.map(x => x * 2);
}
// Mieux : utiliser rest directement
function modernStyle(...args) {
return args.map(x => x * 2);
}
⚖️ Spread vs Méthodes Traditionnelles
| Opération | Ancienne Méthode | Avec Spread/Rest |
|---|---|---|
| Concaténer arrays | arr1.concat(arr2) |
[...arr1, ...arr2] |
| Cloner array | arr.slice() |
[...arr] |
| Cloner objet | Object.assign({}, obj) |
{ ...obj } |
| Max d'un array | Math.max.apply(null, arr) |
Math.max(...arr) |
| Args variables | arguments (pseudo-array) |
...args (vrai array) |
⚠️ Pièges Courants :
- Clone superficiel uniquement :
{...obj}ne clone pas les objets imbriqués (shallow copy). - Rest doit être dernier :
function f(...args, x)❌ Erreur syntaxe. - Ordre important pour objets :
{ ...a, ...b }→ les props debécrasenta. - Performance : Spread crée de nouveaux objets/arrays. Pour de grandes structures, considérez des alternatives.
Best Practice : Utilisez spread/rest pour l'immutabilité (React, Redux). Préférez
...rest à arguments. Pour les clones profonds, utilisez
structuredClone() ou une bibliothèque.