javascript clone object and js copy object workflows fall into shallow copies (new top-level object, shared nested references) and deep copies (nested data duplicated). For javascript copy object in modern engines, structuredClone is usually the best native deep clone; JSON.parse(JSON.stringify(x)) is still common but lossy. If you copy plain data from class instances, remember structuredClone does not preserve the original prototype chain.
Tested on: Node.js v20.18.2. A short note after each snippet describes what you should see in the console.
Quick reference
Shallow copies share nested references; structuredClone is the default deep choice when types are supported; JSON is a narrow, lossy subset.
| Goal | Approach |
|---|---|
| Shallow duplicate | { ...obj } or Object.assign({}, obj) |
| Deep clone, JSON-safe plain data | JSON.parse(JSON.stringify(obj)) (watch Date, undefined, functions, cycles) |
| Deep clone, modern default | structuredClone(obj) when types fit the algorithm |
| Prototype + descriptors snapshot | Object.create(Object.getPrototypeOf(x), Object.getOwnPropertyDescriptors(x)) |
Shallow copy with spread — clone object javascript
Spread { ...obj } is the most common clone object javascript pattern: enumerable own properties copy to a new object in one expression. Nested objects stay aliased—mutating a nested field shows up on both sides—while reassigned top-level keys diverge.
const a = { x: 1, n: { v: 0 } };
const b = { ...a };
b.n.v = 1;
b.x = 2;
console.log(a.n.v, b.n.v, a.x, b.x);You should see one line: 1 1 1 2.
Nested n is shared (both show 1); top-level x diverges (1 vs 2). Same behavior as other spread operator shallow merges.
Shallow copy with Object.assign
Object.assign({}, src) is another js clone object shallow path: it copies enumerable own properties onto a target object. Nested references behave like spread—k.z updates both views in the output below.
const o1 = { k: { z: 1 } };
const o2 = Object.assign({}, o1);
o2.k.z = 9;
console.log(o1.k.z, o2.k.z);You should see one line: 9 9.
for...in manual copy — object clone javascript
A for...in loop is the explicit object clone javascript style when you cannot rely on syntax sugar: copy each key into a fresh object. It is still shallow for nested values, and without Object.hasOwn (or hasOwnProperty checks) you may copy enumerable inherited keys—guard when cloning plain objects that sit on a busy prototype chain.
const originalObject = { type: "van", tyres: 4 };
const clonedObject = {};
for (const key in originalObject) {
clonedObject[key] = originalObject[key];
}
console.log(JSON.stringify(clonedObject));You should see one line: {"type":"van","tyres":4}.
Object.create + property descriptors — js clone object with prototype
Object.create(Object.getPrototypeOf(src), Object.getOwnPropertyDescriptors(src)) preserves prototype linkage and property descriptors—useful when object clone javascript questions mention getters, setters, or non-enumerable fields. Values are still shallow: the series array below is one shared reference between originalObject and clonedObject unless you deep-clone that branch separately.
const originalObject = {
type: "main",
condition: false,
series: [13, 17, 19],
age: 30,
};
const clonedObject = Object.create(
Object.getPrototypeOf(originalObject),
Object.getOwnPropertyDescriptors(originalObject)
);
console.log(JSON.stringify(clonedObject));You should see one line: {"type":"main","condition":false,"series":[13,17,19],"age":30}.
Deep copy with JSON — lossy
JSON.parse(JSON.stringify(obj)) is a narrow javascript copy object hack: it only survives JSON-safe shapes. undefined keys disappear, Date values stringify, functions and symbols vanish, and circular graphs throw—pair this section with copying arrays when the same JSON caveat applies to collections.
const j = { a: 1, u: undefined, d: new Date(0) };
const jc = JSON.parse(JSON.stringify(j));
console.log(JSON.stringify(jc));
console.log(typeof jc.d, jc.d);You should see two lines: first a JSON string without u, then string and an ISO date string (not a Date instance).
undefined is omitted; Date becomes an ISO string, not a Date instance.
Deep copy with structuredClone — javascript clone
structuredClone is the native javascript clone answer for many plain data graphs: nested objects detach, Date, Map, and other structured-cloneable types round-trip, and circular references can be preserved (MDN: structuredClone). It throws DataCloneError for unsupported types such as functions.
const o = {
d: new Date(0),
n: { v: 1 },
m: new Map([["k", 1]]),
};
const c = structuredClone(o);
c.n.v = 2;
console.log(o.n.v, c.n.v, c.d instanceof Date, c.m instanceof Map, c.m.get("k"));You should see one line: 1 2 true true 1.
Nested n is independent (1 vs 2); Date and Map survive cloning.
structuredClone and functions — DataCloneError
Functions are not structured-cloneable: wrapping them in an object and calling structuredClone fails fast with DataCloneError, which is what most js clone object guardrails should catch when user data includes callbacks.
try {
structuredClone({ f() {} });
} catch (e) {
console.log(e.name);
}You should see one line: DataCloneError.
Circular references with structuredClone
Unlike JSON stringify, structuredClone can duplicate graphs that point back to themselves—useful when clone object js payloads include parent/child links. The clone keeps the cycle: y.a === y mirrors the original self-reference.
const x = {};
x.a = x;
const y = structuredClone(x);
console.log(y.a === y);You should see one line: true.
Summary
Match depth to risk: shallow {...obj} when shared nested state is OK; structuredClone when you need detached graphs and supported types; JSON only for JSON-safe payloads.
- Use
{ ...obj }orObject.assign({}, obj)for shallow javascript clone object copies when nested sharing is acceptable. - Use
for...inonly with clear key filtering (Object.hasOwn) when you need explicit object clone javascript control. - Use
Object.create+getOwnPropertyDescriptorswhen prototype and descriptors matter; still plan for nested deep copies. - Reserve JSON round-trip for JSON-safe javascript copy object trees; expect
Date/undefined/function loss. - Prefer
structuredClonefor modern deep javascript clone work when types fit; catchDataCloneErrorfor unsupported values.
References
MDN pages for structuredClone, spread, Object.assign, Object.create, and JSON—core APIs behind javascript clone object and javascript copy object examples in this guide.
- MDN:
structuredClone() - MDN: Spread syntax
- MDN:
Object.assign() - MDN:
Object.create() - MDN:
JSON.stringify() - MDN:
JSON.parse()
