Primitifs, Objets, Shallow & Deep Clone
Utilisez les flĂšches, cliquez ou glissez pour naviguer
1. Primitifs = copie par valeur
Chaque variable a sa propre valeur
2. Objets = copie par référence
Plusieurs variables pointent vers le mĂȘme objet
3. Identifier les bugs de mutation
Modifier une "copie" qui modifie l'original
4. Shallow clone (spread, assign)
Copier le premier niveau seulement
5. Deep clone (structuredClone)
Copier en profondeur tous les niveaux
Le piÚge n°1 : const copie = original
Pourquoi ça ne copie PAS l'objet
Primitifs vs Objets
L'analogie de la maison et de l'adresse
Démo live : mutation involontaire
Modifier une copie qui modifie aussi l'original
Shallow clone : spread & Object.assign
La solution... mais avec un piĂšge!
Deep clone : structuredClone()
La solution moderne et complĂšte
const copie = original
ne copie PAS l'objet!
Ăa copie juste la rĂ©fĂ©rence (l'adresse)
const original = { nom: 'Alice' };
const copie = original;
copie.nom = 'Bob';
console.log(original.nom);
// 'Bob' !!!
On a modifié l'original sans le vouloir!
C'est le bug le plus courant en JavaScript
La différence fondamentale
Primitifs
Copie par valeur
Objets
Copie par référence
Copie par valeur = chaque variable a sa propre copie
string
'hello'
number
42, 3.14
boolean
true, false
null
absence de valeur
undefined
non défini
symbol
identifiant unique
let a = 5;
let b = a; // b reçoit une COPIE de la valeur
b = 10;
console.log(a); // 5 (inchangé!)
Copie par rĂ©fĂ©rence = plusieurs variables pointent vers le MĂME objet
object
{ nom: 'Alice' }
array
[1, 2, 3]
const arr1 = [1, 2, 3];
const arr2 = arr1; // arr2 pointe vers le MĂME tableau!
arr2.push(4);
console.log(arr1); // [1, 2, 3, 4] (modifié!)
Primitif
Tu écris l'adresse sur un papier
Tu copies le papier
Chaque papier a SA propre adresse
Objet
La variable = une adresse
Tu copies l'adresse
Les deux pointent vers la MĂME maison
Si tu peins la maison en rouge depuis l'adresse A...
La maison est aussi rouge depuis l'adresse B!
C'est la MĂME maison, pas deux maisons identiques
Primitifs
let a = 5;
let b = a;
a
5
b
5
Deux boßtes séparées
Objets
const a = { x: 5 };
const b = a;
a
adr: 0x1
b
adr: 0x1
Objet
{ x: 5 }
Deux rĂ©fĂ©rences vers le MĂME objet
Modifier une "copie" modifie l'original
Le bug qui fait perdre des heures de debug
const user = {
nom: 'Alice',
age: 25
};
function anniversaire(personne) {
personne.age++;
return personne;
}
const nouveau = anniversaire(user);
console.log(user.age); // 26 (modifié!)
console.log(nouveau.age); // 26 (mĂȘme objet!)
La fonction a modifié l'objet original!
C'est souvent involontaire et source de bugs
const a = { x: 1 };
const b = { x: 1 };
console.log(a === b);
false
Deux objets diffĂ©rents en mĂ©moire, mĂȘme s'ils ont le mĂȘme contenu!
const c = a;
console.log(a === c); // true (mĂȘme rĂ©fĂ©rence)
Copier le premier niveau
{ ...obj }
Spread operator
Object.assign()
Méthode classique
CrĂ©e un NOUVEL objet avec les mĂȘmes propriĂ©tĂ©s
const original = { nom: 'Alice', age: 25 };
const copie = { ...original };
copie.nom = 'Bob';
console.log(original.nom); // 'Alice' (inchangé!)
console.log(copie.nom); // 'Bob'
Ăa marche! L'original est protĂ©gĂ©.
const original = { nom: 'Alice' };
const copie = Object.assign({}, original);
Le premier argument {} est l'objet cible
Les propriétés de original sont copiées dedans
Préférez le spread { ...obj } - plus moderne et lisible
const original = [1, 2, 3];
const copie = [...original];
// ou
const copie2 = original.slice();
copie.push(4);
console.log(original); // [1, 2, 3] (inchangé)
console.log(copie); // [1, 2, 3, 4]
Les sous-objets restent partagés!
Shallow = superficiel
Ăa ne copie que le premier niveau
const user = {
nom: 'Alice',
adresse: { ville: 'Paris' }
};
const copie = { ...user };
copie.adresse.ville = 'Lyon';
console.log(user.adresse.ville);
// 'Lyon' !!! L'original est modifié!
L'objet adresse est TOUJOURS partagé!
Le spread ne copie que les propriétés du premier niveau
user
nom: 'Alice'
adresse: 0x2
copie
nom: 'Alice'
adresse: 0x2
Objet @0x2
ville: 'Paris'
Partagé!
Le spread copie la VALEUR de chaque propriété
Pour adresse, la valeur est une RĂFĂRENCE (0x2)
Donc les deux pointent vers le mĂȘme sous-objet!
const copie = {
...user,
adresse: { ...user.adresse }
};
Ăa marche, mais...
Fastidieux si l'objet est profond
Erreur-prone si on oublie un niveau
Il existe une meilleure solution!
Copier en profondeur tous les niveaux
structuredClone()
La solution moderne
Copie récursivement TOUS les niveaux
const user = {
nom: 'Alice',
adresse: {
ville: 'Paris',
pays: { nom: 'France' }
}
};
const copie = structuredClone(user);
copie.adresse.pays.nom = 'Espagne';
console.log(user.adresse.pays.nom);
// 'France' (inchangé!)
Fonctionne avec tous les niveaux
Pas besoin de spread imbriqué manuel
GĂšre les tableaux, Map, Set, Date...
Plus puissant que JSON.parse/stringify
Support navigateur moderne
Disponible dans tous les navigateurs récents
Ne fonctionne pas avec les fonctions
Les fonctions ne peuvent pas ĂȘtre clonĂ©es
const copie = JSON.parse(JSON.stringify(user));
Inconvénients
Perd les fonctions
Perd les undefined
Perd les Symbol
Perd les références circulaires
Quand l'utiliser?
Données JSON simples
Compatibilité trÚs ancienne
Préférez structuredClone() - plus robuste!
Confusion const vs immuable
const obj = { x: 1 };
obj.x = 2; // OK! const n'empĂȘche PAS la mutation
obj = {}; // Erreur! const empĂȘche la rĂ©assignation
const = référence constante, pas objet immuable
Oublier que les tableaux sont des objets
const a = [1,2,3];
const b = a;
b.push(4); // a est aussi modifié!
Les tableaux ont le mĂȘme comportement que les objets
Primitifs (string, number, boolean...)
Copie automatique par valeur - pas de souci!
Objet simple (1 niveau)
Utilise { ...obj } ou Object.assign()
Objet imbriqué (plusieurs niveaux)
Utilise structuredClone()
Jamais : copie = original
Ăa ne crĂ©e PAS une copie, juste une autre rĂ©fĂ©rence!
Primitifs
Copie par valeur
Chaque variable = sa propre donnée
Objets
Copie par référence
Plusieurs variables = mĂȘme objet
Shallow
{ ...obj }
Premier niveau seulement
Deep
structuredClone()
Tous les niveaux
L'analogie de la maison est la plus efficace pour expliquer les références
1. Prédire le résultat
Que vaut a aprĂšs: let a = 5; let b = a; b = 10; ?
2. Corriger le bug
Une fonction modifie l'objet original - utiliser le spread
3. Deep clone nécessaire
Créer une vraie copie d'un objet avec sous-objets
4. Identifier le piĂšge
Pourquoi ce code modifie-t-il l'original?
C'est un concept difficile - prévoir du temps pour les exercices
Les bugs de mutation sont les plus difficiles à débugger
Mais maintenant vous savez les éviter!