Cloning Objects in JavaScript: How Not to Break Your Code

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Simple Assignment Is a Trap?

\n

Imagine you are writing a notes application. A user creates a card with a title and text, then wants to make a copy of it to modify it slightly. You write:

\n
const original = { title: 'My Plan', text: 'Buy milk' };\nconst copy = original;\ncopy.title = 'New Plan';\nconsole.log(original.title); // 'New Plan' — oops!
\n

Sound familiar? If so, you've encountered the main feature of objects in JavaScript: they are passed by reference. The assignment copy = original does not create a new object, but merely copies the reference to the same memory location. Any change in copy is reflected in original.

\n

On Stack Overflow, the question "How do I correctly clone a JavaScript object?" has gathered thousands of views and dozens of answers. This is one of the most common problems for beginners and even experienced developers. In this article, we will break down all the ways to clone objects in JavaScript, from simple to advanced, and find out which approach is best for each situation.

\n\n

Shallow Copy: Fast and Simple

\n

Shallow copy creates a new object, but for nested objects (arrays, other objects) it only copies references. This is ideal for flat structures, but dangerous for deep ones.

\n\n

Method 1: Spread Operator (...)

\n

The most modern and readable way:

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

Pros: short syntax, works with arrays and objects. Cons: does not copy methods (functions) and symbol properties.

\n\n

Method 2: Object.assign()

\n

The classic method for copying an object without references at the top level:

\n
const source = { a: 1, b: { c: 2 } };\nconst target = Object.assign({}, source);\ntarget.a = 100; // source.a will not change\ntarget.b.c = 999; // source.b.c will also change — shallow!
\n

This method is especially useful when you need to merge multiple objects: Object.assign({}, obj1, obj2).

\n\n

Method 3: for...in Loop

\n

An ancient but still working method. Useful for understanding the mechanics:

\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

Today it is rarely used, but it perfectly demonstrates how manual object cloning works.

\n\n

Deep Copy: When You Need Everything

\n

If your object contains nested objects, arrays, or dates, shallow copy will let you down. You need deep cloning js.

\n\n

Method 4: JSON.parse + JSON.stringify

\n

The most popular "workaround":

\n
const original = { \n  name: 'Peter', \n  address: { city: 'Moscow', street: 'Tverskaya' },\n  date: new Date()\n};\nconst clone = JSON.parse(JSON.stringify(original));\nclone.address.city = 'SPb';\nconsole.log(original.address.city); // 'Moscow' — hooray!
\n

But there are nuances: this method loses functions, undefined, Symbol, and Date turns into a string. Fine for simple data, not for complex ones.

\n\n

Method 5: structuredClone() — The New Standard

\n

Since 2022, JavaScript has a built-in method structuredClone:

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

Pros: supports Date, Map, Set, ArrayBuffer, recursive references. Cons: does not support functions, DOM elements, Error. Works

Blogs

Book Recommendations