Clonage d'objets en JavaScript : comment ne pas casser le code

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : pourquoi une simple affectation est un piège ?

\n

Imaginez que vous développez une application de notes. Un utilisateur crée une carte avec un titre et un texte, puis souhaite en faire une copie pour la modifier légèrement. Vous écrivez :

\n
const original = { title: 'Mon plan', text: 'Acheter du lait' };\nconst copy = original;\ncopy.title = 'Nouveau plan';\nconsole.log(original.title); // 'Nouveau plan' — oups !
\n

Une situation familière ? Si oui, vous avez rencontré la principale caractéristique des objets en JavaScript : ils sont passés par référence. L'affectation copy = original ne crée pas un nouvel objet, mais copie uniquement la référence vers le même emplacement mémoire. Toute modification dans copy se répercute sur original.

\n

Sur Stack Overflow, la question "How do I correctly clone a JavaScript object?" a recueilli des milliers de vues et des dizaines de réponses. C'est l'un des problèmes les plus fréquents chez les débutants et même les développeurs expérimentés. Dans cet article, nous allons passer en revue toutes les méthodes de clonage d'objets en JavaScript, des plus simples aux plus avancées, et déterminer quelle approche est la meilleure dans chaque situation.

\n\n

Copie superficielle (Shallow copy) : rapide et simple

\n

La copie superficielle crée un nouvel objet, mais pour les objets imbriqués (tableaux, autres objets), elle ne copie que les références. C'est idéal pour les structures plates, mais dangereux pour les structures profondes.

\n\n

Méthode 1 : L'opérateur Spread (…)

\n

La méthode la plus moderne et la plus lisible :

\n
const original = { name: 'Anna', age: 25 };\nconst clone = { ...original };\nclone.age = 30;\nconsole.log(original.age); // 25 — tout va bien !
\n

Avantages : écriture concise, fonctionne avec les tableaux et les objets. Inconvénients : ne copie pas les méthodes (fonctions) ni les propriétés de type symbole.

\n\n

Méthode 2 : Object.assign()

\n

La méthode classique pour copier un objet sans références au niveau supérieur :

\n
const source = { a: 1, b: { c: 2 } };\nconst target = Object.assign({}, source);\ntarget.a = 100; // source.a ne changera pas\ntarget.b.c = 999; // source.b.c changera aussi — superficiel !
\n

Cette méthode est particulièrement utile lorsque vous devez fusionner plusieurs objets : Object.assign({}, obj1, obj2).

\n\n

Méthode 3 : La boucle for…in

\n

Une méthode ancienne, mais toujours fonctionnelle. Utile pour comprendre la mécanique :

\n
function shallowClone(obj) {\n  const clone = {};\n  for (let key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      clone[key] = obj[key];\n    }\n  }\n  return clone;\n}
\n

Aujourd'hui, on l'utilise rarement, mais elle illustre parfaitement comment fonctionne le clonage manuel d'objets.

\n\n

Copie profonde (Deep copy) : quand tout est nécessaire

\n

Si votre objet contient des objets imbriqués, des tableaux ou des dates, la copie superficielle vous décevra. Vous avez besoin d'un clonage profond js.

\n\n

Méthode 4 : JSON.parse + JSON.stringify

\n

La « béquille » la plus populaire :

\n
const original = { \n  name: 'Pierre', \n  address: { city: 'Moscou', street: 'Tverskaïa' },\n  date: new Date()\n};\nconst clone = JSON.parse(JSON.stringify(original));\nclone.address.city = 'Saint-Pétersbourg';\nconsole.log(original.address.city); // 'Moscou' — hourra !
\n

Mais il y a des nuances : cette méthode perd les fonctions, undefined, Symbol, et Date est convertie en chaîne de caractères. Pour des données simples, ça va ; pour des données complexes, non.

\n\n

Méthode 5 : structuredClone() — le nouveau standard

\n

Depuis 2022, JavaScript dispose d'une méthode intégrée structuredClone :

\n
const original = { \n  scores: [10, 20, 30], \n  meta: { level: 'facile' },\n  date: new Date()\n};\nconst clone = structuredClone(original);\nclone.meta.level = 'difficile';\nconsole.log(original.meta.level); // 'facile'
\n

Avantages : prend en charge Date, Map, Set, ArrayBuffer, les références récursives. Inconvénients : ne prend pas en charge les fonctions, les éléments DOM, Error. Fonctionne

Blogs

Book Recommendations