Account imageLoginSign UpAccount image
Loading votes....
Save Question

How to properly deep clone an object in JavaScript fails with Dates and functions.

clock icon

asked 3 months ago

Message icon

1

Eye icon

3

I have a complex object:

js

1const original = {
2 name: "John",
3 date: new Date(),
4 nested: { arr: [1,2,3] },
5 greet: () => "hi"
6};
1const original = {
2 name: "John",
3 date: new Date(),
4 nested: { arr: [1,2,3] },
5 greet: () => "hi"
6};

JSON.parse(JSON.stringify(original)) turns date into a string and loses the greet function. What's a robust solution?

1 Answer

Quick comparison of methods

MethodHandles DatesHandles functionsHandles circular refsPerformance
JSON❌ becomes string❌ removed❌ errorfast
structuredClone (modern)fast
_.cloneDeep (Lodash)moderate
Recursive manualcustomcustomtrickyslow

🏆 Best for 99% of cases – structuredClone (built-in, Node 17+/all modern browsers)

js

1const clone = structuredClone(original);
2console.log(clone.date instanceof Date); // true
3// But functions are still lost (they are not cloneable)
1const clone = structuredClone(original);
2console.log(clone.date instanceof Date); // true
3// But functions are still lost (they are not cloneable)

If you need to copy functions (rarely necessary – better to restructure)

Use Lodash:

js

1import _ from 'lodash';
2const clone = _.cloneDeep(original);
1import _ from 'lodash';
2const clone = _.cloneDeep(original);

Custom recursive for Dates and RegExps (educational)

js

1function deepClone(obj) {
2 if (obj === null || typeof obj !== 'object') return obj;
3 if (obj instanceof Date) return new Date(obj);
4 if (obj instanceof RegExp) return new RegExp(obj);
5 if (Array.isArray(obj)) return obj.map(deepClone);
6
7 const cloned = {};
8 for (let key in obj) {
9 if (obj.hasOwnProperty(key)) {
10 cloned[key] = deepClone(obj[key]);
11 }
12 }
13 return cloned;
14}
1function deepClone(obj) {
2 if (obj === null || typeof obj !== 'object') return obj;
3 if (obj instanceof Date) return new Date(obj);
4 if (obj instanceof RegExp) return new RegExp(obj);
5 if (Array.isArray(obj)) return obj.map(deepClone);
6
7 const cloned = {};
8 for (let key in obj) {
9 if (obj.hasOwnProperty(key)) {
10 cloned[key] = deepClone(obj[key]);
11 }
12 }
13 return cloned;
14}

Note: does not handle circular references.

Recommendation: Use structuredClone for most data. If you need functions, reconsider your architecture – functions imply behavior, which usually shouldn't be deep-copied.

1

Write your answer here

Top Questions