What is the most efficient way to clone a JavaScript object? I've seen obj = eval(uneval(o));
being used, but that's non-standard and only supported by Firefox.
I've done things like obj = JSON.parse(JSON.stringify(o));
but question the efficiency.
I've also seen recursive copying functions with various flaws.
I'm surprised no canonical solution exists.
-
566Eval is not evil. Using eval poorly is. If you are afraid of its side effects you are using it wrong. The side effects you fear are the reasons to use it. Did any one by the way actually answer your question? – Tegra Detra Mar 22 '12 at 14:08
-
15Cloning objects is a tricky business, especially with custom objects of arbitrary collections. Which probably why there is no out-of-the box way to do it. – b01 Mar 11 '13 at 22:25
-
12`eval()` is generally a bad idea because [many Javascript engine's optimisers have to turn off when dealing with variables that are set via `eval`](http://stackoverflow.com/questions/15447519/can-eval-optimize). Just having `eval()` in your code can lead to worse performance. – user56reinstatemonica8 Sep 08 '14 at 13:37
-
12Note that `JSON` method will loose any Javascript types that have no equivalent in JSON. For example: `JSON.parse(JSON.stringify({a:null,b:NaN,c:Infinity,d:undefined,e:function(){},f:Number,g:false}))` will generate `{a: null, b: null, c: null, g: false}` – oriadam May 24 '17 at 13:06
-
The react community has introduced [immutability-helper](https://github.com/kolodny/immutability-helper) – Navid Jul 06 '19 at 07:07
67 Answers
Native deep cloning
There's now a JS standard called "structured cloning", that works experimentally in Node 11 and later, will land in browsers, and which has polyfills for existing systems.
structuredClone(value)
If needed, loading the polyfill first:
import structuredClone from '@ungap/structured-clone';
See this answer for more details.
Older answers
Fast cloning with data loss - JSON.parse/stringify
If you do not use Date
s, functions, undefined
, Infinity
, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, sparse Arrays, Typed Arrays or other complex types within your object, a very simple one liner to deep clone an object is:
JSON.parse(JSON.stringify(object))
const a = {
string: 'string',
number: 123,
bool: false,
nul: null,
date: new Date(), // stringified
undef: undefined, // lost
inf: Infinity, // forced to 'null'
re: /.*/, // lost
}
console.log(a);
console.log(typeof a.date); // Date object
const clone = JSON.parse(JSON.stringify(a));
console.log(clone);
console.log(typeof clone.date); // result of .toISOString()
See Corban's answer for benchmarks.
Reliable cloning using a library
Since cloning objects is not trivial (complex types, circular references, function etc.), most major libraries provide function to clone objects. Don't reinvent the wheel - if you're already using a library, check if it has an object cloning function. For example,
- lodash -
cloneDeep
; can be imported separately via the lodash.clonedeep module and is probably your best choice if you're not already using a library that provides a deep cloning function - AngularJS -
angular.copy
- jQuery -
jQuery.extend(true, { }, oldObject)
;.clone()
only clones DOM elements - just library -
just-clone
; Part of a library of zero-dependency npm modules that do just do one thing. Guilt-free utilities for every occasion.

- 157
- 1
- 11

- 35,521
- 3
- 29
- 19
-
134Beware! `var A = { b: [ { a: [ 1, 2, 3], b: [4, 5, 6], c: [7, 8, 9] } ] }; B = Object.assign( {}, A ); delete B.b[0].b;` It will also modify object A ! – Gabriel Hautclocq Sep 30 '20 at 12:54
-
-
1@GabrielHautclocq You have just discovered what a "shallow copy" means. "@medBouzid" The solution is to "deep copy" the object, instead of shallow copying. – Utku Oct 24 '20 at 22:37
-
I was just demonstrating by example that you cannot use Object.assign for deep cloning an object. – Gabriel Hautclocq Oct 25 '20 at 07:47
-
`Object.assign()` is indeed useless if your object to copy contains arrays in it, especially arrays of objects. Just found that out the hard way... – cst1992 Oct 29 '20 at 09:56
-
17@Gabriel Hautclocq this is because `A.b` or `B.b` are both referring to the same object in the memory. if `A` had a property with a non-object value (like numbers or strings), it'll be copied normally. But when a property containing an object value is copied, it is copied by-reference, not by-value. Also, keep in mind that an Array is an object in JS. proof: `typeof [] == 'object' && [] instanceof Array` – Unicornist Dec 15 '20 at 13:21
-
47@Unicornist Yes and that's why Object.assign does not answer the question which is: "What is the most efficient way to deep clone an object in JavaScript?". So at least it should NOT be presented as an ES6 solution for deep cloning. The title "ES6" is misleading, at least it should be changed to reflect that this is not a deep cloning method. The "shallow" word is easy to overlook and a lot of people just take the simplest solution they find in Stack Overflow without reading everything. It is dangerous to rely on Object.assign for object cloning. Hence my remark. – Gabriel Hautclocq Dec 15 '20 at 13:58
-
6I used a library called really fast deep clone: https://github.com/davidmarkclements/rfdc Worked really well for me. – bakkaa Jan 14 '21 at 16:02
-
1If you experience problems like in first comment, https://github.com/davidmarkclements/rfdc also will make "shallow copy", you'll need to enable option `proto: true`, – Dmitry Mar 08 '21 at 10:48
-
I was scratching my head debugging again & again & turned out File object wasn't being copied with this method & it was being dropped during the deepclone. – Junaid Apr 26 '21 at 12:13
-
@GabrielHautclocq: 1. the proposed solution you're struggling with comes under ES6 (_shallow_ copy). The behaviour you highlight refers to _deep_ copy. Shallow copy only copies the values for the immediate level of the object. If some values are themselves non-atomic, they will be copied by reference. 2. The title ES6 is *NOT* misleading at all. ES6 introduces destructuring as in `{...A1}`, which is better than any `for`-based solution by a landslide. I have a case of a Python-dictionary-like object, where the values are all boolean. The shallow `{...obj}` alternative works like a charm. – Ricardo Apr 27 '21 at 08:34
-
3@Ricardo Surely you can see the history of the answer to see that "(shallow copy)" has been added after "ES6", after I wrote my comment. It's now more clear that this is a shallow copy. – Gabriel Hautclocq Apr 28 '21 at 09:39
-
1Lodash has deprecated per method packages: https://lodash.com/per-method-packages – tagurit Sep 16 '21 at 20:22
-
old news or whatever, but I just had the pleasure of learning this particular part of the jasonstringifyclone: 'If you do not use Dates, etc, etc...' sigh... now rethinking... – Jason Torpy Apr 26 '22 at 02:06
-
2
-
3`structuredClone(...)` is now available in all the meaningful browsers. It would be helpful to see a usage example, especially concerning transferable objects. I'd also argue that `JSON.stringify / parse` can handle dates, you just need to use the reviver (parse) and the replacer (stringify) – Christian Vincenzo Traina Jul 18 '22 at 09:06
-
For me the simple `const element = document.createElement(name); for (const key in object) { element[key] = object[key]; } return element;` would do the job, and i bet it's the fastest – Iglesias Leonardo Jul 25 '22 at 16:33
-
The just-clone library was simple to use and worked well for me. The whole just-xxx library is a great idea – hkong Jul 30 '22 at 18:13
-
1This is not Javascript! This is Node! People should stop answer Javascript question assuming Javascript-based languages like Node and JQuery(argh)! Where is the Vanilla Javascript answer? – Andre Carneiro Mar 31 '23 at 19:01
Checkout this benchmark: http://jsben.ch/#/bWfk9
In my previous tests where speed was a main concern I found
JSON.parse(JSON.stringify(obj))
to be the slowest way to deep clone an object (it is slower than jQuery.extend with deep
flag set true by 10-20%).
jQuery.extend is pretty fast when the deep
flag is set to false
(shallow clone). It is a good option, because it includes some extra logic for type validation and doesn't copy over undefined properties, etc., but this will also slow you down a little.
If you know the structure of the objects you are trying to clone or can avoid deep nested arrays you can write a simple for (var i in obj)
loop to clone your object while checking hasOwnProperty and it will be much much faster than jQuery.
Lastly if you are attempting to clone a known object structure in a hot loop you can get MUCH MUCH MORE PERFORMANCE by simply in-lining the clone procedure and manually constructing the object.
JavaScript trace engines suck at optimizing for..in
loops and checking hasOwnProperty will slow you down as well. Manual clone when speed is an absolute must.
var clonedObject = {
knownProp: obj.knownProp,
..
}
Beware using the JSON.parse(JSON.stringify(obj))
method on Date
objects - JSON.stringify(new Date())
returns a string representation of the date in ISO format, which JSON.parse()
doesn't convert back to a Date
object. See this answer for more details.
Additionally, please note that, in Chrome 65 at least, native cloning is not the way to go. According to JSPerf, performing native cloning by creating a new function is nearly 800x slower than using JSON.stringify which is incredibly fast all the way across the board.
If you are using Javascript ES6 try this native method for cloning or shallow copy.
Object.assign({}, obj);

- 2,070
- 3
- 29
- 47

- 21,270
- 4
- 28
- 34
-
14Note that there are 2 mistakes in your bench: first, it compares some shallow cloning (lodash `_.clone` and `Object.assign`) to some deep cloning (`JSON.parse(JSON.stringify())`). Secondly, it says "deep clone" for lodash but it does a shallow clone instead. – papillon Feb 15 '21 at 14:22
-
Note that when testing in the same benchmarking tool, **object spread** `let obj2 = {...obj}` appears to be more efficient than `Object.assign()`. Approximately ~20% faster. – ragan May 28 '22 at 22:31
-
Note, re Object.assign({}, obj} - this is a shallow copy not a deep clone. This means that if a property is itself an object you only get a reference. – Chrys G Dec 03 '22 at 15:40
-
+1000 for inline cloning. I had hardcoded in a list of the known properties for my object and was looping over them, which gave me about 3000 copies per millisecond. Once I got rid of the loop and wrote out every property in an object literal, that went up to about 2 million copies per millisecond. Absolutely insane speed gains, I never realized loops were that slow. – Isaac King Apr 30 '23 at 20:37
Structured Cloning
2022 update: The structuredClone
global function is already available in Firefox 94, Node 17 and Deno 1.14
The HTML standard includes an internal structured cloning/serialization algorithm that can create deep clones of objects. It is still limited to certain built-in types, but in addition to the few types supported by JSON it also supports Dates, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, sparse Arrays, Typed Arrays, and probably more in the future. It also preserves references within the cloned data, allowing it to support cyclical and recursive structures that would cause errors for JSON.
Support in Node.js:
The structuredClone
global function is provided by Node 17.0:
const clone = structuredClone(original);
Previous versions: The v8
module in Node.js (as of Node 11) exposes the structured serialization API directly, but this functionality is still marked as "experimental", and subject to change or removal in future versions. If you're using a compatible version, cloning an object is as simple as:
const v8 = require('v8');
const structuredClone = obj => {
return v8.deserialize(v8.serialize(obj));
};
Direct Support in Browsers: Available in Firefox 94
The structuredClone
global function will soon be provided by all major browsers (having previously been discussed in whatwg/html#793 on GitHub). It looks / will look like this:
const clone = structuredClone(original);
Until this is shipped, browsers' structured clone implementations are only exposed indirectly.
Asynchronous Workaround: Usable.
The lower-overhead way to create a structured clone with existing APIs is to post the data through one port of a MessageChannels. The other port will emit a message
event with a structured clone of the attached .data
. Unfortunately, listening for these events is necessarily asynchronous, and the synchronous alternatives are less practical.
class StructuredCloner {
constructor() {
this.pendingClones_ = new Map();
this.nextKey_ = 0;
const channel = new MessageChannel();
this.inPort_ = channel.port1;
this.outPort_ = channel.port2;
this.outPort_.onmessage = ({data: {key, value}}) => {
const resolve = this.pendingClones_.get(key);
resolve(value);
this.pendingClones_.delete(key);
};
this.outPort_.start();
}
cloneAsync(value) {
return new Promise(resolve => {
const key = this.nextKey_++;
this.pendingClones_.set(key, resolve);
this.inPort_.postMessage({key, value});
});
}
}
const structuredCloneAsync = window.structuredCloneAsync =
StructuredCloner.prototype.cloneAsync.bind(new StructuredCloner);
Example Use:
const main = async () => {
const original = { date: new Date(), number: Math.random() };
original.self = original;
const clone = await structuredCloneAsync(original);
// They're different objects:
console.assert(original !== clone);
console.assert(original.date !== clone.date);
// They're cyclical:
console.assert(original.self === original);
console.assert(clone.self === clone);
// They contain equivalent values:
console.assert(original.number === clone.number);
console.assert(Number(original.date) === Number(clone.date));
console.log("Assertions complete.");
};
main();
Synchronous Workarounds: Awful!
There are no good options for creating structured clones synchronously. Here are a couple of impractical hacks instead.
history.pushState()
and history.replaceState()
both create a structured clone of their first argument, and assign that value to history.state
. You can use this to create a structured clone of any object like this:
const structuredClone = obj => {
const oldState = history.state;
history.replaceState(obj, null);
const clonedObj = history.state;
history.replaceState(oldState, null);
return clonedObj;
};
Example Use:
'use strict';
const main = () => {
const original = { date: new Date(), number: Math.random() };
original.self = original;
const clone = structuredClone(original);
// They're different objects:
console.assert(original !== clone);
console.assert(original.date !== clone.date);
// They're cyclical:
console.assert(original.self === original);
console.assert(clone.self === clone);
// They contain equivalent values:
console.assert(original.number === clone.number);
console.assert(Number(original.date) === Number(clone.date));
console.log("Assertions complete.");
};
const structuredClone = obj => {
const oldState = history.state;
history.replaceState(obj, null);
const clonedObj = history.state;
history.replaceState(oldState, null);
return clonedObj;
};
main();
Though synchronous, this can be extremely slow. It incurs all of the overhead associated with manipulating the browser history. Calling this method repeatedly can cause Chrome to become temporarily unresponsive.
The Notification
constructor creates a structured clone of its associated data. It also attempts to display a browser notification to the user, but this will silently fail unless you have requested notification permission. In case you have the permission for other purposes, we'll immediately close the notification we've created.
const structuredClone = obj => {
const n = new Notification('', {data: obj, silent: true});
n.onshow = n.close.bind(n);
return n.data;
};
Example Use:
'use strict';
const main = () => {
const original = { date: new Date(), number: Math.random() };
original.self = original;
const clone = structuredClone(original);
// They're different objects:
console.assert(original !== clone);
console.assert(original.date !== clone.date);
// They're cyclical:
console.assert(original.self === original);
console.assert(clone.self === clone);
// They contain equivalent values:
console.assert(original.number === clone.number);
console.assert(Number(original.date) === Number(clone.date));
console.log("Assertions complete.");
};
const structuredClone = obj => {
const n = new Notification('', {data: obj, silent: true});
n.close();
return n.data;
};
main();
-
58
-
323As the guy who implemented pushState in Firefox, I feel an odd mix of pride and revulsion at this hack. Well done, guys. – Justin L. Aug 14 '14 at 18:37
-
1pushState or Notification hack does not work for some object types like Function – Shishir Arora Jul 03 '19 at 20:06
-
@ShishirArora You're right, I just tried it, it throws a 'Uncaught DOMException: The object could not be cloned.' This is also true for the Notification hack. – ADJenks Jul 10 '20 at 21:39
-
Would anyone happen to know if the native v8 Structured Cloning is susceptible to prototype pollution? – Alexis Tyler Nov 12 '21 at 06:58
-
5**April 2022 update:** `structuredClone` is available in FF 94+, Chrome 98+ and Safari 15.4+ and Edge 98+, so in all current versions of the major browsers! – oelna Apr 10 '22 at 15:17
-
2Abuse of API like the above (no offense at @Jeremy's valiant attempts to show solutions) will continue as long as HTML authoring committees are fundamentally unable to design APIs of quality and continue churning out APIs that are broken-by-design. For instance, the structured clone algorithm defines a procedure that is rigid (hardly extendible by a script, say) and at the same time leaves too much to the user agent. Firefox, f.e., is unable to clone `Error` objects, for instance -- but MDN proudly states it supports `structuredClone` and friends, although this is a manner of interpretation. – Armen Michaeli May 04 '22 at 12:57
-
1@ArmenMichaeli THIS. HTML authoring committees are fundamentally unable to design APIs of quality It is appalling how they manage to so such a bad job over and over again. It has been done in different tech stacks decades ago. Everything in JS is an object. There is NO vanilla 1 liner which deep clones an object. This is the definition of insanity. It should be as simple as = is by reference and := is by value or something like that. – DanteTheSmith Mar 24 '23 at 14:25
-
1`structuredClone` is far less performant than other solutions offered here, like using Object.assign or lodash cloneDeep. The question specifically asked for it, so it is important to mention. This may change as native implementation do change - but for now, it's the worst option. – SnirD May 01 '23 at 16:42
Assuming that you have only properties and not any functions in your object, you can just use:
var newObject = JSON.parse(JSON.stringify(oldObject));

- 2,628
- 4
- 26
- 43

- 724
- 2
- 11
- 22
-
2
-
11
-
1
-
2IMHO I think this is the best way to clone a data object. Especially when u are dealing with data fetched from an API and state management. I believe that if you need to clone an object that was created with native Javascript constructs (functions, dates, NaN...) there is something wrong or most probably you do not need to clone it. – albanx May 17 '22 at 09:40
-
1This is inefficient for types like **NaN, Infinity, undefined** etc. JSON.stringify converts them to null. Reference: **JSON.parse(JSON.stringify({a:null,b:undefined}))** equals **{a: null}**. – zlatanned Aug 27 '22 at 12:32
If there wasn't any builtin one, you could try:
function clone(obj) {
if (obj === null || typeof (obj) !== 'object' || 'isActiveClone' in obj)
return obj;
if (obj instanceof Date)
var temp = new obj.constructor(); //or new Date(obj);
else
var temp = obj.constructor();
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
obj['isActiveClone'] = null;
temp[key] = clone(obj[key]);
delete obj['isActiveClone'];
}
}
return temp;
}

- 1,528
- 1
- 16
- 20

- 40,958
- 16
- 80
- 86
-
6
-
It seems to track circular references. E.g.: `const a = {}; a['selfref'] = a; a['text'] = 'something'; alert(a.selfref.text);` If you tried to clone the above `a` object without the `isActiveClone` part, you'd end up in an infinite recursion (because of the recursive `clone()` call on property `selfref`). – Peti29 Mar 13 '23 at 11:29
-
One the best answers here that handle `Arrays` and `Cyclic References ` as well as clean code with acceptable speed (performance) – S.Serpooshan Apr 04 '23 at 18:45
The efficient way to clone(not deep-clone) an object in one line of code
An Object.assign
method is part of the ECMAScript 2015 (ES6) standard and does exactly what you need.
var clone = Object.assign({}, obj);
The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.
The polyfill to support older browsers:
if (!Object.assign) {
Object.defineProperty(Object, 'assign', {
enumerable: false,
configurable: true,
writable: true,
value: function(target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert first argument to object');
}
var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) {
continue;
}
nextSource = Object(nextSource);
var keysArray = Object.keys(nextSource);
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) {
to[nextKey] = nextSource[nextKey];
}
}
}
return to;
}
});
}

- 1
- 1

- 4,019
- 4
- 33
- 32
-
103This doesn't recursively copy so doesn't really offer a solution to the problem of cloning an object. – mwhite Mar 08 '16 at 19:56
-
7This method worked, although I tested a few and _.extend({}, (obj)) was BY FAR the fastest: 20x faster than JSON.parse and 60% faster than Object.assign, for example. It copies all sub-objects quite well. – Nico May 09 '16 at 19:57
-
18@mwhite there is a difference between clone and deep-clone. This answer does in fact clone, but it doesn't deep-clone. – Meirion Hughes Jun 08 '16 at 12:08
-
4the question was about recursive copies. Object.assign, as well as the given custom assign, do not copy recursively – johannes_lalala Mar 04 '21 at 01:52
-
Deep copy by performance:
Ranked from best to worst, based on benchmarks
https://www.measurethat.net/Benchmarks/Show/17502/0/deep-copy-comparison
- spread operator
...
(primitive arrays - only) slice()
(primitive arrays - only)splice(0)
(primitive arrays - only)concat()
(primitive arrays - only)JSON.parse(JSON.stringify())
(primitive and literal arrays - only)- custom function, as seen below (any array)
- Lodash's
_.cloneDeep()
(any array) - jQuery's
$.extend()
(any array) - Underscore's
_.clone()
(primitive and literal arrays - only)
Where:
- primitives = strings, numbers, and booleans
- literals = object literals
{}
, array literals[]
- any = primitives, literals, and prototypes
Deep copy an array of primitives:
let arr1a = [1, 'a', true];
To deep copy arrays with primitives only (i.e. numbers, strings, and booleans), reassignment, slice()
, concat()
, and Underscore's clone()
can be used.
Where spread has the fastest performance:
let arr1b = [...arr1a];
And where slice()
has better performance than splice(0)
and concat()
let arr1d = arr1a.slice();
let arr1c = arr1a.splice(0);
let arr1e = arr1a.concat();
Deep copy an array of primitive and object literals:
let arr2a = [1, 'a', true, {}, []];
let arr2b = JSON.parse(JSON.stringify(arr2a));
Deep copy an array of primitive, object literals, and prototypes:
let arr3a = [1, 'a', true, {}, [], new Object()];
Write a custom function (has faster performance than jQuery $.extend()
):
function copy(aObject) {
// Prevent undefined objects
// if (!aObject) return aObject;
let bObject = Array.isArray(aObject) ? [] : {};
let value;
for (const key in aObject) {
// Prevent self-references to parent object
// if (Object.is(aObject[key], aObject)) continue;
value = aObject[key];
bObject[key] = (typeof value === "object") ? copy(value) : value;
}
return bObject;
}
let arr3b = copy(arr3a);
Or use third-party utility functions:
let arr3c = $.extend(true, [], arr3a); // jQuery
let arr3d = _.cloneDeep(arr3a); // Lodash

- 16,217
- 5
- 62
- 51
-
2With for-in loop you should use ```hasOwnProperty``` to exclude inherited properties. I use (possibly even faster) plain for loop over ```Object.keys```. – mikiqex Jun 29 '21 at 06:19
-
3In a deep copy, wouldn't you want to copy the inherited properties as well? Also, note that invoking the `hasOwnProperty` method, creates a performance hit (pushing the function call on and off the stack, and executing the method code) for every key. – tim-montague Jun 30 '21 at 17:47
-
1Most of these are not deep clones at all, and therefore doesn't make sense to benchmark them against eachother. – zkldi Nov 08 '22 at 15:07
-
1in my tests, the `slice()` is very faster than `splice(0)`, although both of them are shallow copy – S.Serpooshan Apr 04 '23 at 17:12
-
@S.Serpooshan - In agreement, answer has been updated based on the following benchmarks (https://www.measurethat.net/Benchmarks/Show/17502/0/deep-copy-comparison) – tim-montague Apr 04 '23 at 23:01
This is what I'm using:
function cloneObject(obj) {
var clone = {};
for(var i in obj) {
if(typeof(obj[i])=="object" && obj[i] != null)
clone[i] = cloneObject(obj[i]);
else
clone[i] = obj[i];
}
return clone;
}

- 10,222
- 12
- 66
- 129

- 241
- 1
- 3
- 2
-
Trying: var a = {b: 1, c: 3, d: { a: 10, g: 20, h: { today: new Date() }}}; Not working for me. But `Object.assign({}, a)` did. – Martin Luther ETOUMAN Apr 08 '21 at 19:58
-
-
-
This does not work for arrays, as it will turn them into objects: `{ a: ["foo", "bar"} }` will become `{ a { "0": "foo", "1": "bar" } }`. – zkldi Nov 08 '22 at 15:08
-
I have extended this function for complex object but right now it won't support Date https://stackblitz.com/edit/typescript-vudfgn?file=index.ts – MohanaRajesh Feb 03 '23 at 16:11
Code:
// extends 'from' object with members from 'to'. If 'to' is null, a deep clone of 'from' is returned
function extend(from, to)
{
if (from == null || typeof from != "object") return from;
if (from.constructor != Object && from.constructor != Array) return from;
if (from.constructor == Date || from.constructor == RegExp || from.constructor == Function ||
from.constructor == String || from.constructor == Number || from.constructor == Boolean)
return new from.constructor(from);
to = to || new from.constructor();
for (var name in from)
{
to[name] = typeof to[name] == "undefined" ? extend(from[name], null) : to[name];
}
return to;
}
Test:
var obj =
{
date: new Date(),
func: function(q) { return 1 + q; },
num: 123,
text: "asdasd",
array: [1, "asd"],
regex: new RegExp(/aaa/i),
subobj:
{
num: 234,
text: "asdsaD"
}
}
var clone = extend(obj);

- 10,832
- 7
- 57
- 70
Deep copying objects in JavaScript (I think the best and the simplest)
1. Using JSON.parse(JSON.stringify(object));
var obj = {
a: 1,
b: {
c: 2
}
}
var newObj = JSON.parse(JSON.stringify(obj));
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } }
2.Using created method
function cloneObject(obj) {
var clone = {};
for(var i in obj) {
if(obj[i] != null && typeof(obj[i])=="object")
clone[i] = cloneObject(obj[i]);
else
clone[i] = obj[i];
}
return clone;
}
var obj = {
a: 1,
b: {
c: 2
}
}
var newObj = cloneObject(obj);
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } }
3. Using Lo-Dash's _.cloneDeep link lodash
var obj = {
a: 1,
b: {
c: 2
}
}
var newObj = _.cloneDeep(obj);
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } }
4. Using Object.assign() method
var obj = {
a: 1,
b: 2
}
var newObj = _.clone(obj);
obj.b = 20;
console.log(obj); // { a: 1, b: 20 }
console.log(newObj); // { a: 1, b: 2 }
BUT WRONG WHEN
var obj = {
a: 1,
b: {
c: 2
}
}
var newObj = Object.assign({}, obj);
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 20 } } --> WRONG
// Note: Properties on the prototype chain and non-enumerable properties cannot be copied.
5.Using Underscore.js _.clone link Underscore.js
var obj = {
a: 1,
b: 2
}
var newObj = _.clone(obj);
obj.b = 20;
console.log(obj); // { a: 1, b: 20 }
console.log(newObj); // { a: 1, b: 2 }
BUT WRONG WHEN
var obj = {
a: 1,
b: {
c: 2
}
}
var newObj = _.cloneDeep(obj);
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 20 } } --> WRONG
// (Create a shallow-copied clone of the provided plain object. Any nested objects or arrays will be copied by reference, not duplicated.)
JSBEN.CH Performance Benchmarking Playground 1~3 http://jsben.ch/KVQLd

- 2,070
- 3
- 29
- 47

- 4,400
- 1
- 33
- 33
-
1Hey, your last example is wrong. In my opinion, you must use _clone and not _cloneDeep for the wrong example. – kenanyildiz90 Dec 10 '19 at 07:20
-
1
-
1Method #2 is vulnerable to prototype pollution, similar to what happened to lodash's `defaultsDeep`. It should not copy if `(i === '__proto__')`, and it should not copy if `(i === 'constuctor' && typeof obj[i] === 'function')`. – Frank Fajardo Mar 07 '21 at 08:46
Cloning an object was always a concern in JS, but it was all about before ES6, I list different ways of copying an object in JavaScript below, imagine you have the Object below and would like to have a deep copy of that:
var obj = {a:1, b:2, c:3, d:4};
There are few ways to copy this object, without changing the origin:
ES5+, Using a simple function to do the copy for you:
function deepCopyObj(obj) { if (null == obj || "object" != typeof obj) return obj; if (obj instanceof Date) { var copy = new Date(); copy.setTime(obj.getTime()); return copy; } if (obj instanceof Array) { var copy = []; for (var i = 0, len = obj.length; i < len; i++) { copy[i] = deepCopyObj(obj[i]); } return copy; } if (obj instanceof Object) { var copy = {}; for (var attr in obj) { if (obj.hasOwnProperty(attr)) copy[attr] = deepCopyObj(obj[attr]); } return copy; } throw new Error("Unable to copy obj this object."); }
ES5+, using
JSON.parse
andJSON.stringify
.var deepCopyObj = JSON.parse(JSON.stringify(obj));
Angular:
var deepCopyObj = angular.copy(obj);
jQuery:
var deepCopyObj = jQuery.extend(true, {}, obj);
Underscore.js & Lodash:
var deepCopyObj = _.cloneDeep(obj); //latest version of Underscore.js makes shallow copy
Hope these help…
var clone = function() {
var newObj = (this instanceof Array) ? [] : {};
for (var i in this) {
if (this[i] && typeof this[i] == "object") {
newObj[i] = this[i].clone();
}
else
{
newObj[i] = this[i];
}
}
return newObj;
};
Object.defineProperty( Object.prototype, "clone", {value: clone, enumerable: false});

- 24,778
- 15
- 68
- 99

- 9,096
- 3
- 52
- 44
There’s a library (called “clone”), that does this quite well. It provides the most complete recursive cloning/copying of arbitrary objects that I know of. It also supports circular references, which is not covered by the other answers, yet.
You can find it on npm, too. It can be used for the browser as well as Node.js.
Here is an example on how to use it:
Install it with
npm install clone
or package it with Ender.
ender build clone [...]
You can also download the source code manually.
Then you can use it in your source code.
var clone = require('clone');
var a = { foo: { bar: 'baz' } }; // inital value of a
var b = clone(a); // clone a -> b
a.foo.bar = 'foo'; // change a
console.log(a); // { foo: { bar: 'foo' } }
console.log(b); // { foo: { bar: 'baz' } }
(Disclaimer: I’m the author of the library.)

- 7,157
- 7
- 47
- 74
I know this is an old post, but I thought this may be of some help to the next person who stumbles along.
As long as you don't assign an object to anything it maintains no reference in memory. So to make an object that you want to share among other objects, you'll have to create a factory like so:
var a = function(){
return {
father:'zacharias'
};
},
b = a(),
c = a();
c.father = 'johndoe';
alert(b.father);
-
This isn't a deep clone of an existing object, this is just creating a new object. – zkldi Nov 08 '22 at 15:09
If you're using it, the Underscore.js library has a clone method.
var newObject = _.clone(oldObject);
Here's a version of ConroyP's answer above that works even if the constructor has required parameters:
//If Object.create isn't already defined, we just do the simple shim,
//without the second argument, since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
object_create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}
function deepCopy(obj) {
if(obj == null || typeof(obj) !== 'object'){
return obj;
}
//make sure the returned object has the same prototype as the original
var ret = object_create(obj.constructor.prototype);
for(var key in obj){
ret[key] = deepCopy(obj[key]);
}
return ret;
}
This function is also available in my simpleoo library.
Edit:
Here's a more robust version (thanks to Justin McCandless this now supports cyclic references as well):
/**
* Deep copy an object (make copies of all its object properties, sub-properties, etc.)
* An improved version of http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
* that doesn't break if the constructor has required parameters
*
* It also borrows some code from http://stackoverflow.com/a/11621004/560114
*/
function deepCopy(src, /* INTERNAL */ _visited, _copiesVisited) {
if(src === null || typeof(src) !== 'object'){
return src;
}
//Honor native/custom clone methods
if(typeof src.clone == 'function'){
return src.clone(true);
}
//Special cases:
//Date
if(src instanceof Date){
return new Date(src.getTime());
}
//RegExp
if(src instanceof RegExp){
return new RegExp(src);
}
//DOM Element
if(src.nodeType && typeof src.cloneNode == 'function'){
return src.cloneNode(true);
}
// Initialize the visited objects arrays if needed.
// This is used to detect cyclic references.
if (_visited === undefined){
_visited = [];
_copiesVisited = [];
}
// Check if this object has already been visited
var i, len = _visited.length;
for (i = 0; i < len; i++) {
// If so, get the copy we already made
if (src === _visited[i]) {
return _copiesVisited[i];
}
}
//Array
if (Object.prototype.toString.call(src) == '[object Array]') {
//[].slice() by itself would soft clone
var ret = src.slice();
//add it to the visited array
_visited.push(src);
_copiesVisited.push(ret);
var i = ret.length;
while (i--) {
ret[i] = deepCopy(ret[i], _visited, _copiesVisited);
}
return ret;
}
//If we've reached here, we have a regular object
//make sure the returned object has the same prototype as the original
var proto = (Object.getPrototypeOf ? Object.getPrototypeOf(src): src.__proto__);
if (!proto) {
proto = src.constructor.prototype; //this line would probably only be reached by very old browsers
}
var dest = object_create(proto);
//add this object to the visited array
_visited.push(src);
_copiesVisited.push(dest);
for (var key in src) {
//Note: this does NOT preserve ES5 property attributes like 'writable', 'enumerable', etc.
//For an example of how this could be modified to do so, see the singleMixin() function
dest[key] = deepCopy(src[key], _visited, _copiesVisited);
}
return dest;
}
//If Object.create isn't already defined, we just do the simple shim,
//without the second argument, since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
object_create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}

- 12,169
- 4
- 59
- 75
The following creates two instances of the same object. I found it and am using it currently. It's simple and easy to use.
var objToCreate = JSON.parse(JSON.stringify(cloneThis));

- 18,402
- 15
- 86
- 123

- 189
- 5
- 19
Crockford suggests (and I prefer) using this function:
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var newObject = object(oldObject);
It's terse, works as expected and you don't need a library.
EDIT:
This is a polyfill for Object.create
, so you also can use this.
var newObject = Object.create(oldObject);
NOTE: If you use some of this, you may have problems with some iteration who use hasOwnProperty
. Because, create
create new empty object who inherits oldObject
. But it is still useful and practical for cloning objects.
For exemple if oldObject.a = 5;
newObject.a; // is 5
but:
oldObject.hasOwnProperty(a); // is true
newObject.hasOwnProperty(a); // is false

- 1,653
- 19
- 23

- 2,421
- 27
- 23
function clone(obj)
{ var clone = {};
clone.prototype = obj.prototype;
for (property in obj) clone[property] = obj[property];
return clone;
}

- 98,437
- 31
- 224
- 236
Lodash has a nice _.cloneDeep(value) method:
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false

- 143,271
- 52
- 317
- 404

- 60,462
- 79
- 252
- 386
Shallow copy one-liner (ECMAScript 5th edition):
var origin = { foo : {} };
var copy = Object.keys(origin).reduce(function(c,k){c[k]=origin[k];return c;},{});
console.log(origin, copy);
console.log(origin == copy); // false
console.log(origin.foo == copy.foo); // true
And shallow copy one-liner (ECMAScript 6th edition, 2015):
var origin = { foo : {} };
var copy = Object.assign({}, origin);
console.log(origin, copy);
console.log(origin == copy); // false
console.log(origin.foo == copy.foo); // true

- 494
- 5
- 13

- 7,055
- 7
- 46
- 77
-
This is a **shallow copy** and a **deep clone** like the question asked for. This will not work for nested objects. – zkldi Nov 08 '22 at 15:10
There seems to be no ideal deep clone operator yet for array-like objects. As the code below illustrates, John Resig's jQuery cloner turns arrays with non-numeric properties into objects that are not arrays, and RegDwight's JSON cloner drops the non-numeric properties. The following tests illustrate these points on multiple browsers:
function jQueryClone(obj) {
return jQuery.extend(true, {}, obj)
}
function JSONClone(obj) {
return JSON.parse(JSON.stringify(obj))
}
var arrayLikeObj = [[1, "a", "b"], [2, "b", "a"]];
arrayLikeObj.names = ["m", "n", "o"];
var JSONCopy = JSONClone(arrayLikeObj);
var jQueryCopy = jQueryClone(arrayLikeObj);
alert("Is arrayLikeObj an array instance?" + (arrayLikeObj instanceof Array) +
"\nIs the jQueryClone an array instance? " + (jQueryCopy instanceof Array) +
"\nWhat are the arrayLikeObj names? " + arrayLikeObj.names +
"\nAnd what are the JSONClone names? " + JSONCopy.names)

- 9,914
- 3
- 52
- 82

- 119
- 2
- 5
I have two good answers depending on whether your objective is to clone a "plain old JavaScript object" or not.
Let's also assume that your intention is to create a complete clone with no prototype references back to the source object. If you're not interested in a complete clone, then you can use many of the Object.clone() routines provided in some of the other answers (Crockford's pattern).
For plain old JavaScript objects, a tried and true good way to clone an object in modern runtimes is quite simply:
var clone = JSON.parse(JSON.stringify(obj));
Note that the source object must be a pure JSON object. This is to say, all of its nested properties must be scalars (like boolean, string, array, object, etc). Any functions or special objects like RegExp or Date will not be cloned.
Is it efficient? Heck yes. We've tried all kinds of cloning methods and this works best. I'm sure some ninja could conjure up a faster method. But I suspect we're talking about marginal gains.
This approach is just simple and easy to implement. Wrap it into a convenience function and if you really need to squeeze out some gain, go for at a later time.
Now, for non-plain JavaScript objects, there isn't a really simple answer. In fact, there can't be because of the dynamic nature of JavaScript functions and inner object state. Deep cloning a JSON structure with functions inside requires you recreate those functions and their inner context. And JavaScript simply doesn't have a standardized way of doing that.
The correct way to do this, once again, is via a convenience method that you declare and reuse within your code. The convenience method can be endowed with some understanding of your own objects so you can make sure to properly recreate the graph within the new object.
We're written our own, but the best general approach I've seen is covered here:
http://davidwalsh.name/javascript-clone
This is the right idea. The author (David Walsh) has commented out the cloning of generalized functions. This is something you might choose to do, depending on your use case.
The main idea is that you need to special handle the instantiation of your functions (or prototypal classes, so to speak) on a per-type basis. Here, he's provided a few examples for RegExp and Date.
Not only is this code brief, but it's also very readable. It's pretty easy to extend.
Is this efficient? Heck yes. Given that the goal is to produce a true deep-copy clone, then you're going to have to walk the members of the source object graph. With this approach, you can tweak exactly which child members to treat and how to manually handle custom types.
So there you go. Two approaches. Both are efficient in my view.

- 30,738
- 21
- 105
- 131

- 289
- 4
- 5
Just because I didn't see AngularJS mentioned and thought that people might want to know...
angular.copy
also provides a method of deep copying objects and arrays.

- 11,391
- 14
- 81
- 114
-
or it might be used the same way as jQiery extend: `angular.extend({},obj);` – Galvani Sep 21 '16 at 09:07
-
2@Galvani: It should be noted that `jQuery.extend` and `angular.extend` are both shallow copies. `angular.copy` is a deep copy. – Dan Atkinson Oct 15 '16 at 18:41
Only when you can use ECMAScript 6 or transpilers.
Features:
- Won't trigger getter/setter while copying.
- Preserves getter/setter.
- Preserves prototype informations.
- Works with both object-literal and functional OO writing styles.
Code:
function clone(target, source){
for(let key in source){
// Use getOwnPropertyDescriptor instead of source[key] to prevent from trigering setter/getter.
let descriptor = Object.getOwnPropertyDescriptor(source, key);
if(descriptor.value instanceof String){
target[key] = new String(descriptor.value);
}
else if(descriptor.value instanceof Array){
target[key] = clone([], descriptor.value);
}
else if(descriptor.value instanceof Object){
let prototype = Reflect.getPrototypeOf(descriptor.value);
let cloneObject = clone({}, descriptor.value);
Reflect.setPrototypeOf(cloneObject, prototype);
target[key] = cloneObject;
}
else {
Object.defineProperty(target, key, descriptor);
}
}
let prototype = Reflect.getPrototypeOf(source);
Reflect.setPrototypeOf(target, prototype);
return target;
}
-
-
This will create a reference to the same object instance (_not_ deep-copying it) if used with objects that have a `null` prototype, since `Object.create(null) instanceof Object` is false. – CherryDT Oct 31 '21 at 18:05
I am late to answer this question, but I have an another way of cloning the object:
function cloneObject(obj) {
if (obj === null || typeof(obj) !== 'object')
return obj;
var temp = obj.constructor(); // changed
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
obj['isActiveClone'] = null;
temp[key] = cloneObject(obj[key]);
delete obj['isActiveClone'];
}
}
return temp;
}
var b = cloneObject({"a":1,"b":2}); // calling
which is much better and faster then:
var a = {"a":1,"b":2};
var b = JSON.parse(JSON.stringify(a));
and
var a = {"a":1,"b":2};
// Deep copy
var newObject = jQuery.extend(true, {}, a);
I have bench-marked the code and you can test the results here:
and sharing the results:
References: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

- 14,289
- 18
- 86
- 145

- 869
- 10
- 28
-
its funny but when I run your tests it actually shoed me that method 1 is the slowest one – Antoniossss Apr 26 '18 at 08:30
-
-
Only solution that worked for me! Had to deep clone an object that contained other objects with function properties. Perfect. – Phoenix Mar 12 '21 at 17:22
-
Why do you set `obj['isActiveClone'] = null` and then delete it? And why don't you call `obj.hasOwnProperty(key)`? – Aykut Kllic Apr 16 '21 at 07:50
This isn't generally the most efficient solution, but it does what I need. Simple test cases below...
function clone(obj, clones) {
// Makes a deep copy of 'obj'. Handles cyclic structures by
// tracking cloned obj's in the 'clones' parameter. Functions
// are included, but not cloned. Functions members are cloned.
var new_obj,
already_cloned,
t = typeof obj,
i = 0,
l,
pair;
clones = clones || [];
if (obj === null) {
return obj;
}
if (t === "object" || t === "function") {
// check to see if we've already cloned obj
for (i = 0, l = clones.length; i < l; i++) {
pair = clones[i];
if (pair[0] === obj) {
already_cloned = pair[1];
break;
}
}
if (already_cloned) {
return already_cloned;
} else {
if (t === "object") { // create new object
new_obj = new obj.constructor();
} else { // Just use functions as is
new_obj = obj;
}
clones.push([obj, new_obj]); // keep track of objects we've cloned
for (key in obj) { // clone object members
if (obj.hasOwnProperty(key)) {
new_obj[key] = clone(obj[key], clones);
}
}
}
}
return new_obj || obj;
}
Cyclic array test...
a = []
a.push("b", "c", a)
aa = clone(a)
aa === a //=> false
aa[2] === a //=> false
aa[2] === a[2] //=> false
aa[2] === aa //=> true
Function test...
f = new Function
f.a = a
ff = clone(f)
ff === f //=> true
ff.a === a //=> false

- 67
- 1
- 8
For the people who want to use the JSON.parse(JSON.stringify(obj))
version, but without losing the Date objects, you can use the second argument of parse
method to convert the strings back to Date:
function clone(obj) {
var regExp = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
return JSON.parse(JSON.stringify(obj), function(k, v) {
if (typeof v === 'string' && regExp.test(v))
return new Date(v)
return v;
})
}
// usage:
var original = {
a: [1, null, undefined, 0, {a:null}, new Date()],
b: {
c(){ return 0 }
}
}
var cloned = clone(original)
console.log(cloned)
I disagree with the answer with the greatest votes here. A Recursive Deep Clone is much faster than the JSON.parse(JSON.stringify(obj)) approach mentioned.
- Jsperf ranks it number one here: https://jsperf.com/deep-copy-vs-json-stringify-json-parse/5
- Jsben from the answer above updated to show that a recursive deep clone beats all the others mentioned: http://jsben.ch/13YKQ
And here's the function for quick reference:
function cloneDeep (o) {
let newO
let i
if (typeof o !== 'object') return o
if (!o) return o
if (Object.prototype.toString.apply(o) === '[object Array]') {
newO = []
for (i = 0; i < o.length; i += 1) {
newO[i] = cloneDeep(o[i])
}
return newO
}
newO = {}
for (i in o) {
if (o.hasOwnProperty(i)) {
newO[i] = cloneDeep(o[i])
}
}
return newO
}

- 20,132
- 13
- 91
- 118
-
2I liked this approach but it doesn't handle dates properly; consider adding something like `if(o instanceof Date) return new Date(o.valueOf());` after checking for null ` – Luis Aug 21 '17 at 22:53
-
-
In latest stable Firefox, this is way longer than the other strategies at that Jsben.ch link, by an order of magnitude or more. It beats the others in the wrong direction. – WBT Jan 14 '19 at 18:38
Here is a comprehensive clone() method that can clone any JavaScript object. It handles almost all the cases:
function clone(src, deep) {
var toString = Object.prototype.toString;
if (!src && typeof src != "object") {
// Any non-object (Boolean, String, Number), null, undefined, NaN
return src;
}
// Honor native/custom clone methods
if (src.clone && toString.call(src.clone) == "[object Function]") {
return src.clone(deep);
}
// DOM elements
if (src.nodeType && toString.call(src.cloneNode) == "[object Function]") {
return src.cloneNode(deep);
}
// Date
if (toString.call(src) == "[object Date]") {
return new Date(src.getTime());
}
// RegExp
if (toString.call(src) == "[object RegExp]") {
return new RegExp(src);
}
// Function
if (toString.call(src) == "[object Function]") {
//Wrap in another method to make sure == is not true;
//Note: Huge performance issue due to closures, comment this :)
return (function(){
src.apply(this, arguments);
});
}
var ret, index;
//Array
if (toString.call(src) == "[object Array]") {
//[].slice(0) would soft clone
ret = src.slice();
if (deep) {
index = ret.length;
while (index--) {
ret[index] = clone(ret[index], true);
}
}
}
//Object
else {
ret = src.constructor ? new src.constructor() : {};
for (var prop in src) {
ret[prop] = deep
? clone(src[prop], true)
: src[prop];
}
}
return ret;
};

- 30,738
- 21
- 105
- 131

- 79
- 2
- 2
-
It converts primitives into wrapper objects, not a good solution in most cases. – Danubian Sailor Aug 01 '14 at 09:58
-
@DanubianSailor - I don't think it does...it seems to return primitives right away from the start, and doesn't seem to be doing anything to them that would turn them into wrapper objects as they are returned. – Jimbo Jonny Feb 02 '16 at 18:06
// obj target object, vals source object
var setVals = function (obj, vals) {
if (obj && vals) {
for (var x in vals) {
if (vals.hasOwnProperty(x)) {
if (obj[x] && typeof vals[x] === 'object') {
obj[x] = setVals(obj[x], vals[x]);
} else {
obj[x] = vals[x];
}
}
}
}
return obj;
};

- 591
- 5
- 12

- 21
- 1
- 2
AngularJS
Well if you're using angular you could do this too
var newObject = angular.copy(oldObject);

- 18,215
- 7
- 67
- 72
In JavaScript, you can write your
deepCopy
method like
function deepCopy(src) {
let target = Array.isArray(src) ? [] : {};
for (let prop in src) {
let value = src[prop];
if(value && typeof value === 'object') {
target[prop] = deepCopy(value);
} else {
target[prop] = value;
}
}
return target;
}

- 1,185
- 1
- 10
- 7
-
1This is vulnerable to global Object pollution. It should not copy `prop` if `(prop === 'constuctor' && typeof src[prop] === 'function')` or if `(prop === '__proto__')` – Frank Fajardo Mar 07 '21 at 08:49
I use the npm clone library. Apparently it also works in the browser.
https://www.npmjs.com/package/clone
let a = clone(b)

- 41,701
- 23
- 172
- 300

- 1,405
- 1
- 15
- 18
In my experience, a recursive version vastly outperforms JSON.parse(JSON.stringify(obj))
. Here is a modernized recursive deep object copy function which can fit on a single line:
function deepCopy(obj) {
return Object.keys(obj).reduce((v, d) => Object.assign(v, {
[d]: (obj[d].constructor === Object) ? deepCopy(obj[d]) : obj[d]
}), {});
}
This is performing around 40 times faster than the JSON.parse...
method.

- 302
- 3
- 13
-
2Pseudocode would be: for each key, assign its value to the same key in a new object (shallow copy). However if the value is of type `Object` (can't shallow copy), the function recursively calls itself with the value as an argument. – Parabolord Aug 15 '18 at 20:48
-
1Too bad it doesn't work right when the value is an array. But, shouldn't be too difficult to modify to get it to work for that case. – zenw0lf Aug 24 '19 at 22:30
-
-
Doesn't work for null as it tries to access `null.constructor`, doesn't work for arrays as it turns them into objects. – zkldi Nov 08 '22 at 15:05
As recursion is just too expensive for JavaScript, and most answers I have found are using recursion, while JSON approach will skip the non-JSON-convertible parts (Function, etc.). So I did a little research and found this trampoline technique to avoid it. Here's the code:
/*
* Trampoline to avoid recursion in JavaScript, see:
* https://www.integralist.co.uk/posts/functional-recursive-javascript-programming/
*/
function trampoline() {
var func = arguments[0];
var args = [];
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
var currentBatch = func.apply(this, args);
var nextBatch = [];
while (currentBatch && currentBatch.length > 0) {
currentBatch.forEach(function(eachFunc) {
var ret = eachFunc();
if (ret && ret.length > 0) {
nextBatch = nextBatch.concat(ret);
}
});
currentBatch = nextBatch;
nextBatch = [];
}
};
/*
* Deep clone an object using the trampoline technique.
*
* @param target {Object} Object to clone
* @return {Object} Cloned object.
*/
function clone(target) {
if (typeof target !== 'object') {
return target;
}
if (target == null || Object.keys(target).length == 0) {
return target;
}
function _clone(b, a) {
var nextBatch = [];
for (var key in b) {
if (typeof b[key] === 'object' && b[key] !== null) {
if (b[key] instanceof Array) {
a[key] = [];
}
else {
a[key] = {};
}
nextBatch.push(_clone.bind(null, b[key], a[key]));
}
else {
a[key] = b[key];
}
}
return nextBatch;
};
var ret = target instanceof Array ? [] : {};
(trampoline.bind(null, _clone))(target, ret);
return ret;
};
-
3Tail call recursion is actually very efficient in most implementations of JavaScript, and is required to be optimized in ES6. – rich remer Feb 13 '16 at 05:19
-
Hi I did a little test back then, and when the target object becomes complex, the call stack would easily overflow, though I didn't take any notes, hopefully in es6 this will be a big op. – Bodhi Hu Apr 22 '16 at 12:36
-
2Stack would easily overflow, probably because of the circular reference. – Yichong Jan 11 '17 at 01:16
Single-line ECMAScript 6 solution (special object types like Date/Regex not handled):
const clone = (o) =>
typeof o === 'object' && o !== null ? // only clone objects
(Array.isArray(o) ? // if cloning an array
o.map(e => clone(e)) : // clone each of its elements
Object.keys(o).reduce( // otherwise reduce every key in the object
(r, k) => (r[k] = clone(o[k]), r), {} // and save its cloned value into a new object
)
) :
o; // return non-objects as is
var x = {
nested: {
name: 'test'
}
};
var y = clone(x);
console.log(x.nested !== y.nested);

- 34,790
- 6
- 87
- 99

- 5,521
- 4
- 30
- 35
-
5Please provide an explanation alongside a code chunk so that others with a similar question can easily understand what is happening. As it stands now, this question is in a low quality posts review queue. – coatless Jul 17 '16 at 22:50
-
1Please edit with more information. Code-only and "try this" answers are discouraged, because they contain no searchable content, and don't explain why someone should "try this". – Paritosh Jul 18 '16 at 09:17
Lodash has a function that handles that for you like so.
var foo = {a: 'a', b: {c:'d', e: {f: 'g'}}};
var bar = _.cloneDeep(foo);
// bar = {a: 'a', b: {c:'d', e: {f: 'g'}}}
Read the docs here.

- 2,603
- 5
- 31
- 40
-
I ended up using this, since the JSON.parse(JSON.stringify(obj)) does not keep the original object prototype – tommyalvarez Jul 11 '17 at 17:27
-
This is my goto answer. Except that I use Lodash's merge, keeps the syntax somewhat consistent for deep and shallow copying. `//Deep copy: _.merge({},foo) //Shallow copy: Object.Assign({}, foo)` – RobbyD Jul 20 '17 at 07:30
ES 2017 example:
let objectToCopy = someObj;
let copyOfObject = {};
Object.defineProperties(copyOfObject, Object.getOwnPropertyDescriptors(objectToCopy));
// copyOfObject will now be the same as objectToCopy

- 4,134
- 2
- 31
- 50
-
Thank you for the answer. I tried your approach, but unfortunately, it does not work. Because it could be some kind of mistake on my side, I ask you for check my [example in JSFiddle](https://jsfiddle.net/x8k9avf2/9/) and if it will be some mistake on my side, I'll vote up for your answer. – Takeshi Tokugawa YD Jun 10 '18 at 03:39
-
When I run your fiddle, I get `{ foo: 1, bar: { fooBar: 22, fooBaz: 33, fooFoo: 11 }, baz: 3}` and `{ foo: 1, bar: { fooBar: 22, fooBaz: 44, fooFoo: 11 }, baz: 4}`. Is that not what you expect to happen? – codeMonkey Jun 10 '18 at 03:50
-
what you pasted is what I expected. I don't understand why, but I see `fooBaz: 44` for both `testObj2` and `testObj3` in console... ([screenshot](http://prntscr.com/jt5tj0)) – Takeshi Tokugawa YD Jun 10 '18 at 03:55
-
3
There are a lot of answers, but none of them gave the desired effect I needed. I wanted to utilize the power of jQuery's deep copy... However, when it runs into an array, it simply copies the reference to the array and deep copies the items in it. To get around this, I made a nice little recursive function that will create a new array automatically.
(It even checks for kendo.data.ObservableArray if you want it to! Though, make sure you make sure you call kendo.observable(newItem) if you want the Arrays to be observable again.)
So, to fully copy an existing item, you just do this:
var newItem = jQuery.extend(true, {}, oldItem);
createNewArrays(newItem);
function createNewArrays(obj) {
for (var prop in obj) {
if ((kendo != null && obj[prop] instanceof kendo.data.ObservableArray) || obj[prop] instanceof Array) {
var copy = [];
$.each(obj[prop], function (i, item) {
var newChild = $.extend(true, {}, item);
createNewArrays(newChild);
copy.push(newChild);
});
obj[prop] = copy;
}
}
}

- 4,178
- 1
- 32
- 39
I usually use var newObj = JSON.parse( JSON.stringify(oldObje) );
but, here's a more proper way:
var o = {};
var oo = Object.create(o);
(o === oo); // => false
Watch legacy browsers!

- 9,785
- 4
- 61
- 46
-
The second way needs a Prototype, I prefer the first way, even if it's not the best one on performance due to you can use with a lot of browsers and with Node JS. – Hola Soy Edu Feliz Navidad May 03 '14 at 10:03
-
That's cool and all but suppose o has a property a. Now does oo.hasOwnProperty('a')? – user420667 Mar 29 '16 at 23:54
-
No -- o is essentially added as a prototype of oo. This is likely not going to be the desired behavior, which is why 99.9% of the serialize() methods I write use the JSON approach mentioned above. I basically always use JSON, and there're other caveats exposed when using Object.create. – Cody Mar 30 '16 at 02:30
-
1No, watch this code! `Object.create` doesn't necessary create a copy of an object instead it uses the older object as a prototype for the clone – 16kb Jun 22 '18 at 01:07
For future reference, the current draft of ECMAScript 6 introduces Object.assign as a way of cloning objects. Example code would be:
var obj1 = { a: true, b: 1 };
var obj2 = Object.assign(obj1);
console.log(obj2); // { a: true, b: 1 }
At the time of writing support is limited to Firefox 34 in browsers so it’s not usable in production code just yet (unless you’re writing a Firefox extension of course).

- 30,738
- 21
- 105
- 131

- 6,159
- 4
- 40
- 67
-
3You probably meant `obj2 = Object.assign({}, obj1)`. Your current code is equivalent to `obj2 = obj1`. – Oriol Jan 25 '15 at 11:10
-
6This is a shallow-clone. `const o1 = { a: { deep: 123 } }; const o2 = Object.assign({}, o1); o2.a.deep = 456;` now `o1.a.deep === 456` too. – Josh from Qaribou Feb 06 '17 at 14:21
-
3
-
4Wow, another useless answer. Taken from MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign : `Warning for Deep Clone - For deep cloning, we need to use other alternatives because Object.assign() copies property values. If the source value is a reference to an object, it only copies that reference value.` – basickarl Apr 21 '17 at 10:04
There are so many ways to achieve this, but if you want to do this without any library, you can use the following:
const cloneObject = (oldObject) => {
let newObject = oldObject;
if (oldObject && typeof oldObject === 'object') {
if(Array.isArray(oldObject)) {
newObject = [];
} else if (Object.prototype.toString.call(oldObject) === '[object Date]' && !isNaN(oldObject)) {
newObject = new Date(oldObject.getTime());
} else {
newObject = {};
for (let i in oldObject) {
newObject[i] = cloneObject(oldObject[i]);
}
}
}
return newObject;
}
Let me know what you think.

- 634
- 7
- 18
Object.assign({},sourceObj)
only clones the object if their property is not having reference type key.
ex
obj={a:"lol",b:["yes","no","maybe"]}
clonedObj = Object.assign({},obj);
clonedObj.b.push("skip")// changes will reflected to the actual obj as well because of its reference type.
obj.b //will also console => yes,no,maybe,skip
So for the deep cloning is not possible to achieve in this way.
The best solution that works is
var obj = Json.stringify(yourSourceObj)
var cloned = Json.parse(obj);

- 431
- 7
- 8
-
-
This answer is not correct - `Object.assign()` is a shallow copy, and `Json` is not the right way to use the `JSON` utilities. – zkldi Nov 08 '22 at 15:01
This is the fastest method I have created that doesn't use the prototype, so it will maintain hasOwnProperty in the new object.
The solution is to iterate the top level properties of the original object, make two copies, delete each property from the original and then reset the original object and return the new copy. It only has to iterate as many times as top level properties. This saves all the if
conditions to check if each property is a function, object, string, etc., and doesn't have to iterate each descendant property.
The only drawback is that the original object must be supplied with its original created namespace, in order to reset it.
copyDeleteAndReset:function(namespace,strObjName){
var obj = namespace[strObjName],
objNew = {},objOrig = {};
for(i in obj){
if(obj.hasOwnProperty(i)){
objNew[i] = objOrig[i] = obj[i];
delete obj[i];
}
}
namespace[strObjName] = objOrig;
return objNew;
}
var namespace = {};
namespace.objOrig = {
'0':{
innerObj:{a:0,b:1,c:2}
}
}
var objNew = copyDeleteAndReset(namespace,'objOrig');
objNew['0'] = 'NEW VALUE';
console.log(objNew['0']) === 'NEW VALUE';
console.log(namespace.objOrig['0']) === innerObj:{a:0,b:1,c:2};

- 30,738
- 21
- 105
- 131

- 21
- 1
- 1
-
This is a shallow copy and doesn't work for arrays. It also declares `i` in the global scope. – zkldi Nov 08 '22 at 15:03
This is my version of object cloner. This is a stand-alone version of the jQuery method, with only few tweaks and adjustments. Check out the fiddle. I've used a lot of jQuery until the day I realized that I'd use only this function most of the time x_x.
The usage is the same as described into the jQuery API:
- Non-deep clone:
extend(object_dest, object_source);
- Deep clone:
extend(true, object_dest, object_source);
One extra function is used to define if object is proper to be cloned.
/**
* This is a quasi clone of jQuery's extend() function.
* by Romain WEEGER for wJs library - www.wexample.com
* @returns {*|{}}
*/
function extend() {
// Make a copy of arguments to avoid JavaScript inspector hints.
var to_add, name, copy_is_array, clone,
// The target object who receive parameters
// form other objects.
target = arguments[0] || {},
// Index of first argument to mix to target.
i = 1,
// Mix target with all function arguments.
length = arguments.length,
// Define if we merge object recursively.
deep = false;
// Handle a deep copy situation.
if (typeof target === 'boolean') {
deep = target;
// Skip the boolean and the target.
target = arguments[ i ] || {};
// Use next object as first added.
i++;
}
// Handle case when target is a string or something (possible in deep copy)
if (typeof target !== 'object' && typeof target !== 'function') {
target = {};
}
// Loop trough arguments.
for (false; i < length; i += 1) {
// Only deal with non-null/undefined values
if ((to_add = arguments[ i ]) !== null) {
// Extend the base object.
for (name in to_add) {
// We do not wrap for loop into hasOwnProperty,
// to access to all values of object.
// Prevent never-ending loop.
if (target === to_add[name]) {
continue;
}
// Recurse if we're merging plain objects or arrays.
if (deep && to_add[name] && (is_plain_object(to_add[name]) || (copy_is_array = Array.isArray(to_add[name])))) {
if (copy_is_array) {
copy_is_array = false;
clone = target[name] && Array.isArray(target[name]) ? target[name] : [];
}
else {
clone = target[name] && is_plain_object(target[name]) ? target[name] : {};
}
// Never move original objects, clone them.
target[name] = extend(deep, clone, to_add[name]);
}
// Don't bring in undefined values.
else if (to_add[name] !== undefined) {
target[name] = to_add[name];
}
}
}
}
return target;
}
/**
* Check to see if an object is a plain object
* (created using "{}" or "new Object").
* Forked from jQuery.
* @param obj
* @returns {boolean}
*/
function is_plain_object(obj) {
// Not plain objects:
// - Any object or value whose internal [[Class]] property is not "[object Object]"
// - DOM nodes
// - window
if (obj === null || typeof obj !== "object" || obj.nodeType || (obj !== null && obj === obj.window)) {
return false;
}
// Support: Firefox <20
// The try/catch suppresses exceptions thrown when attempting to access
// the "constructor" property of certain host objects, i.e. |window.location|
// https://bugzilla.mozilla.org/show_bug.cgi?id=814622
try {
if (obj.constructor && !this.hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf")) {
return false;
}
}
catch (e) {
return false;
}
// If the function hasn't returned already, we're confident that
// |obj| is a plain object, created by {} or constructed with new Object
return true;
}

- 30,738
- 21
- 105
- 131

- 429
- 2
- 9
-
1You may want to add `|| typeof target[name] !== "undefined"` when testing `if (target === to_add[name]) { continue; }` to not overwrite the existing members of `target`. For example `var a={hello:"world", foo:"bar"}; var b={hello:"you"}; extend(b, a);` we expect to find `b => {hello:"you", foo:"bar"}`, but with your code we find: `b => {hello:"world", foo:"bar"}` – AymKdn May 26 '17 at 10:05
-
In my case I expected indeed to overwrite existing members, so the current behaviour was the wright one for this usage. But thank you to add this helpful suggestion. – weeger Jun 16 '17 at 13:01
Here is my way of deep cloning a object with ES2015
default value and spread operator
const makeDeepCopy = (obj, copy = {}) => {
for (let item in obj) {
if (typeof obj[item] === 'object') {
makeDeepCopy(obj[item], copy)
}
if (obj.hasOwnProperty(item)) {
copy = {
...obj
}
}
}
return copy
}
const testObj = {
"type": "object",
"properties": {
"userId": {
"type": "string",
"chance": "guid"
},
"emailAddr": {
"type": "string",
"chance": {
"email": {
"domain": "fake.com"
}
},
"pattern": ".+@fake.com"
}
},
"required": [
"userId",
"emailAddr"
]
}
const makeDeepCopy = (obj, copy = {}) => {
for (let item in obj) {
if (typeof obj[item] === 'object') {
makeDeepCopy(obj[item], copy)
}
if (obj.hasOwnProperty(item)) {
copy = {
...obj
}
}
}
return copy
}
console.log(makeDeepCopy(testObj))

- 1,184
- 2
- 16
- 23
-
Tour `test` object is **too naive**. it must have some `undefined`, functions, dates and `null` and not just a bunch of strings – vsync Oct 24 '20 at 13:13
-
Doesn't work for fields where the value is null, nor does it work for fields where the value is an array. – zkldi Nov 08 '22 at 15:00
Looking through this long list of answers nearly all the solutions have been covered except one that I am aware of. This is the list of VANILLA JS ways of deep cloning an object.
JSON.parse(JSON.stringify( obj ) );
Through history.state with pushState or replaceState
Web Notifications API but this has the downside of asking the user for permissions.
Doing your own recursive loop through the object to copy each level.
The answer I didn't see -> Using ServiceWorkers. The messages (objects) passed back and forth between the page and the ServiceWorker script will be deep clones of any object.

- 61
- 4
-
All these have already been converted either in the answers or the comments. I would vote this up if you gave unique code examples for each one though. – Jack G Apr 07 '18 at 00:24
Hope this helps.
function deepClone(obj) {
/*
* Duplicates an object
*/
var ret = null;
if (obj !== Object(obj)) { // primitive types
return obj;
}
if (obj instanceof String || obj instanceof Number || obj instanceof Boolean) { // string objecs
ret = obj; // for ex: obj = new String("Spidergap")
} else if (obj instanceof Date) { // date
ret = new obj.constructor();
} else
ret = Object.create(obj.constructor.prototype);
var prop = null;
var allProps = Object.getOwnPropertyNames(obj); //gets non enumerables also
var props = {};
for (var i in allProps) {
prop = allProps[i];
props[prop] = false;
}
for (i in obj) {
props[i] = i;
}
//now props contain both enums and non enums
var propDescriptor = null;
var newPropVal = null; // value of the property in new object
for (i in props) {
prop = obj[i];
propDescriptor = Object.getOwnPropertyDescriptor(obj, i);
if (Array.isArray(prop)) { //not backward compatible
prop = prop.slice(); // to copy the array
} else
if (prop instanceof Date == true) {
prop = new prop.constructor();
} else
if (prop instanceof Object == true) {
if (prop instanceof Function == true) { // function
if (!Function.prototype.clone) {
Function.prototype.clone = function() {
var that = this;
var temp = function tmp() {
return that.apply(this, arguments);
};
for (var ky in this) {
temp[ky] = this[ky];
}
return temp;
}
}
prop = prop.clone();
} else // normal object
{
prop = deepClone(prop);
}
}
newPropVal = {
value: prop
};
if (propDescriptor) {
/*
* If property descriptors are there, they must be copied
*/
newPropVal.enumerable = propDescriptor.enumerable;
newPropVal.writable = propDescriptor.writable;
}
if (!ret.hasOwnProperty(i)) // when String or other predefined objects
Object.defineProperty(ret, i, newPropVal); // non enumerable
}
return ret;
}

- 5,864
- 15
- 60
- 90
My scenario was a bit different. I had an object with nested objects as well as functions. Therefore, Object.assign()
and JSON.stringify()
were not solutions to my problem. Using third-party libraries was not an option for me neither.
Hence, I decided to make a simple function to use built-in methods to copy an object with its literal properties, its nested objects, and functions.
let deepCopy = (target, source) => {
Object.assign(target, source);
// check if there's any nested objects
Object.keys(source).forEach((prop) => {
/**
* assign function copies functions and
* literals (int, strings, etc...)
* except for objects and arrays, so:
*/
if (typeof(source[prop]) === 'object') {
// check if the item is, in fact, an array
if (Array.isArray(source[prop])) {
// clear the copied referenece of nested array
target[prop] = Array();
// iterate array's item and copy over
source[prop].forEach((item, index) => {
// array's items could be objects too!
if (typeof(item) === 'object') {
// clear the copied referenece of nested objects
target[prop][index] = Object();
// and re do the process for nested objects
deepCopy(target[prop][index], item);
} else {
target[prop].push(item);
}
});
// otherwise, treat it as an object
} else {
// clear the copied referenece of nested objects
target[prop] = Object();
// and re do the process for nested objects
deepCopy(target[prop], source[prop]);
}
}
});
};
Here's a test code:
let a = {
name: 'Human',
func: () => {
console.log('Hi!');
},
prop: {
age: 21,
info: {
hasShirt: true,
hasHat: false
}
},
mark: [89, 92, { exam: [1, 2, 3] }]
};
let b = Object();
deepCopy(b, a);
a.name = 'Alien';
a.func = () => { console.log('Wassup!'); };
a.prop.age = 1024;
a.prop.info.hasShirt = false;
a.mark[0] = 87;
a.mark[1] = 91;
a.mark[2].exam = [4, 5, 6];
console.log(a); // updated props
console.log(b);
For efficiency-related concerns, I believe this is the simplest and most efficient solution to the problem I had. I would appreciate any comments on this algorithm that could make it more efficient.

- 365
- 2
- 8
-
This code replaces `null` inside objects with `{}`, as `typeof null === "object"` – zkldi Nov 08 '22 at 14:59
Use Object.create()
to get the prototype
and support for instanceof
, and use a for()
loop to get enumerable keys:
function cloneObject(source) {
var key,value;
var clone = Object.create(source);
for (key in source) {
if (source.hasOwnProperty(key) === true) {
value = source[key];
if (value!==null && typeof value==="object") {
clone[key] = cloneObject(value);
} else {
clone[key] = value;
}
}
}
return clone;
}

- 3,814
- 1
- 30
- 30
-
Great answer! I think this is the one of the only methods to keep setters and getter intact. This solved my problem. Thanks! (see: http://stackoverflow.com/questions/33207028/javascript-setter-and-getter-of-object-lost-after-angular-copy) – lepe Oct 20 '15 at 05:54
-
Wouldn't you want to use clone = `Object.create(Object.getPrototypeOf(source))`, instead of inheriting properties which you also overwrite? – Jeremy Apr 07 '16 at 17:47
-
Interesting. Though, using `getPrototypeOf` on an `Array` turns its indexes into keys of a new `Object`. – Steven Vachon Apr 11 '16 at 16:47
-
Doesn't work for arrays, as it uses `Object.create()` to try and create arrays. – zkldi Nov 08 '22 at 14:58
For future reference, one can use this code
ES6:
_clone: function(obj){
let newObj = {};
for(let i in obj){
if(typeof(obj[i]) === 'object' && Object.keys(obj[i]).length){
newObj[i] = clone(obj[i]);
} else{
newObj[i] = obj[i];
}
}
return Object.assign({},newObj);
}
ES5:
function clone(obj){
let newObj = {};
for(let i in obj){
if(typeof(obj[i]) === 'object' && Object.keys(obj[i]).length){
newObj[i] = clone(obj[i]);
} else{
newObj[i] = obj[i];
}
}
return Object.assign({},newObj);
}
E.g
var obj ={a:{b:1,c:3},d:4,e:{f:6}}
var xc = clone(obj);
console.log(obj); //{a:{b:1,c:3},d:4,e:{f:6}}
console.log(xc); //{a:{b:1,c:3},d:4,e:{f:6}}
xc.a.b = 90;
console.log(obj); //{a:{b:1,c:3},d:4,e:{f:6}}
console.log(xc); //{a:{b:90,c:3},d:4,e:{f:6}}

- 150
- 4
- 18
-
2this does not handle arrays, that are, indeed, objects as well. – Soldeplata Saketos Oct 30 '17 at 08:02
-
class Handler {
static deepCopy (obj) {
if (Object.prototype.toString.call(obj) === '[object Array]') {
const result = [];
for (let i = 0, len = obj.length; i < len; i++) {
result[i] = Handler.deepCopy(obj[i]);
}
return result;
} else if (Object.prototype.toString.call(obj) === '[object Object]') {
const result = {};
for (let prop in obj) {
result[prop] = Handler.deepCopy(obj[prop]);
}
return result;
}
return obj;
}
}

- 1,111
- 13
- 10
Without touching the prototypical inheritance you may deep lone objects and arrays as follows;
function objectClone(o){
var ot = Array.isArray(o);
return o !== null && typeof o === "object" ? Object.keys(o)
.reduce((r,k) => o[k] !== null && typeof o[k] === "object" ? (r[k] = objectClone(o[k]),r)
: (r[k] = o[k],r), ot ? [] : {})
: o;
}
var obj = {a: 1, b: {c: 2, d: {e: 3, f: {g: 4, h: null}}}},
arr = [1,2,[3,4,[5,6,[7]]]],
nil = null,
clobj = objectClone(obj),
clarr = objectClone(arr),
clnil = objectClone(nil);
console.log(clobj, obj === clobj);
console.log(clarr, arr === clarr);
console.log(clnil, nil === clnil);
clarr[2][2][2] = "seven";
console.log(arr, clarr);

- 25,060
- 6
- 56
- 76
What about asynchronous object cloning done by a Promise
?
async function clone(thingy /**/)
{
if(thingy instanceof Promise)
{
throw Error("This function cannot clone Promises.");
}
return thingy;
}

- 12,550
- 7
- 61
- 73
-
2Hold on, 5 upvoters, how does it work? I forgot it myself and this looks counterintuitive, now that one and half years has past. – Константин Ван Aug 27 '19 at 16:13
-
-
Does `Promise.resolve(value)` resolve a cloned `value`? I doubt it, past myself. – Константин Ван Aug 22 '20 at 22:41
-
This doesn't do any cloning at all. Infact, it does nothing. This is equivalent to `const newObj = obj`. – zkldi Nov 08 '22 at 14:56
For a shallow copy there is a great, simple method introduced in ECMAScript2018 standard. It involves the use of Spread Operator :
let obj = {a : "foo", b:"bar" , c:10 , d:true , e:[1,2,3] };
let objClone = { ...obj };
I have tested it in Chrome browser, both objects are stored in different locations, so changing immediate child values in either will not change the other. Though (in the example) changing a value in e
will effect both copies.
This technique is very simple and straight forward. I consider this a true Best Practice for this question once and for all.

- 450
- 3
- 16

- 2,546
- 2
- 14
- 19
-
1updating e in objClone will still update e in obj. This is still only a shallow copy. The question explicitly asks for a deep clone. – Taugenichts Jun 27 '18 at 14:59
-
@Taugenichts... did you tested it? The method works perfectly. [Spread_syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) `Spread in object literals` section – mickro Jun 27 '18 at 17:06
-
1yes, I tested it. run this code: objClone.e[4] = 5; console.log(obj.e); You will see obj.e being updated – Taugenichts Jun 27 '18 at 17:35
-
2Because both are stored in different locations merely means it is at least a shallow copy. Look at where `obj.e` and `objClone.e` are stored; you will find that they are stored in the same location. – Lupus Ossorum Jun 29 '18 at 21:24
-
1Thanks a lot, guys@LupusOssorum @Taugenichts for pointing this out. I tested it myself and found out what you guys identified here. But do you have any idea why the array still does not change memory, though ECMA2018 boasts of this as a feature. – Vikram K Jul 10 '18 at 09:29
-
From mozilla's docs on it under Spread in object literals: "Shallow-cloning (excluding prototype) or merging of objects is now possible using a shorter syntax than Object.assign()." - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax – Taugenichts Sep 13 '18 at 15:31
-
I think that this is the best solution if you want to generalize your object cloning algorithm.
It can be used with or without jQuery, although I recommend leaving jQuery's extend method out if you want you the cloned object to have the same "class" as the original one.
function clone(obj){
if(typeof(obj) == 'function')//it's a simple function
return obj;
//of it's not an object (but could be an array...even if in javascript arrays are objects)
if(typeof(obj) != 'object' || obj.constructor.toString().indexOf('Array')!=-1)
if(JSON != undefined)//if we have the JSON obj
try{
return JSON.parse(JSON.stringify(obj));
}catch(err){
return JSON.parse('"'+JSON.stringify(obj)+'"');
}
else
try{
return eval(uneval(obj));
}catch(err){
return eval('"'+uneval(obj)+'"');
}
// I used to rely on jQuery for this, but the "extend" function returns
//an object similar to the one cloned,
//but that was not an instance (instanceof) of the cloned class
/*
if(jQuery != undefined)//if we use the jQuery plugin
return jQuery.extend(true,{},obj);
else//we recursivley clone the object
*/
return (function _clone(obj){
if(obj == null || typeof(obj) != 'object')
return obj;
function temp () {};
temp.prototype = obj;
var F = new temp;
for(var key in obj)
F[key] = clone(obj[key]);
return F;
})(obj);
}

- 22,383
- 32
- 112
- 130

- 41,171
- 10
- 96
- 108
This is my solution without using any library or native javascript function.
function deepClone(obj) {
if (typeof obj !== "object") {
return obj;
} else {
let newObj =
typeof obj === "object" && obj.length !== undefined ? [] : {};
for (let key in obj) {
if (key) {
newObj[key] = deepClone(obj[key]);
}
}
return newObj;
}
}

- 3,453
- 1
- 13
- 15
-
-
Doesn't work for objects which happen to have a property called `length`, like `{ foo: "bar", length: "10cm" }`, as it doesn't infer arrays properly. Also, turns `{ foo: null }` into `{ foo: {} }`, because it doesn't check for null properly. – zkldi Nov 08 '22 at 14:54
Requires new-ish browsers, but...
Let's extend the native Object and get a real .extend()
;
Object.defineProperty(Object.prototype, 'extend', {
enumerable: false,
value: function(){
var that = this;
Array.prototype.slice.call(arguments).map(function(source){
var props = Object.getOwnPropertyNames(source),
i = 0, l = props.length,
prop;
for(; i < l; ++i){
prop = props[i];
if(that.hasOwnProperty(prop) && typeof(that[prop]) === 'object'){
that[prop] = that[prop].extend(source[prop]);
}else{
Object.defineProperty(that, prop, Object.getOwnPropertyDescriptor(source, prop));
}
}
});
return this;
}
});
Just pop that in prior to any code that uses .extend() on an object.
Example:
var obj1 = {
node1: '1',
node2: '2',
node3: 3
};
var obj2 = {
node1: '4',
node2: 5,
node3: '6'
};
var obj3 = ({}).extend(obj1, obj2);
console.log(obj3);
// Object {node1: "4", node2: 5, node3: "6"}

- 109
- 1
- 4
-
1Mutating prototypes is generally considered bad practice, with the only exception being for shims. – Josh from Qaribou Feb 06 '17 at 14:23
This is a solution with recursion:
obj = {
a: { b: { c: { d: ['1', '2'] } } },
e: 'Saeid'
}
const Clone = function (obj) {
const container = Array.isArray(obj) ? [] : {}
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
if(typeof obj[key] == 'object') {
container[key] = Clone(obj[key])
}
else
container[key] = obj[key].slice()
}
return container
}
console.log(Clone(obj))

- 85
- 10
When your object is nested and it contains data object, other structured object or some property object, etc then using JSON.parse(JSON.stringify(object))
or Object.assign({}, obj)
or $.extend(true, {}, obj)
will not work. In that case use lodash. It is simple and easy..
var obj = {a: 25, b: {a: 1, b: 2}, c: new Date(), d: anotherNestedObject };
var A = _.cloneDeep(obj);
Now A will be your new cloned of obj without any references..

- 4,407
- 2
- 23
- 33
if you find yourself doing this type of thing regular ( eg- creating undo redo functionality ) it might be worth looking into Immutable.js
const map1 = Immutable.fromJS( { a: 1, b: 2, c: { d: 3 } } );
const map2 = map1.setIn( [ 'c', 'd' ], 50 );
console.log( `${ map1.getIn( [ 'c', 'd' ] ) } vs ${ map2.getIn( [ 'c', 'd' ] ) }` ); // "3 vs 50"

- 5,895
- 4
- 27
- 16
With the proposal of the new method Object.fromEntries() that is supported on newer versions of some browsers (reference). I want to contribute with the next recursive approach:
const obj = {
key1: {key11: "key11", key12: "key12", key13: {key131: 22}},
key2: {key21: "key21", key22: "key22"},
key3: "key3",
key4: [1,2,3, {key: "value"}]
}
const cloneObj = (obj) =>
{
if (Object(obj) !== obj)
return obj;
else if (Array.isArray(obj))
return obj.map(cloneObj);
return Object.fromEntries(Object.entries(obj).map(
([k,v]) => ([k, cloneObj(v)])
));
}
// Clone the original object.
let newObj = cloneObj(obj);
// Make changes on the original object.
obj.key1.key11 = "TEST";
obj.key3 = "TEST";
obj.key1.key13.key131 = "TEST";
obj.key4[1] = "TEST";
obj.key4[3].key = "TEST";
// Display both objects on the console.
console.log("Original object: ", obj);
console.log("Cloned object: ", newObj);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

- 16,846
- 2
- 23
- 48
As this question is having lot of attention and answers with reference to inbuilt features such as Object.assign or custom code to deep clone, i would like to share some libraries to deep clone,
1. esclone
npm install --savedev esclone https://www.npmjs.com/package/esclone
Example use in ES6:
import esclone from "esclone";
const rockysGrandFather = {
name: "Rockys grand father",
father: "Don't know :("
};
const rockysFather = {
name: "Rockys Father",
father: rockysGrandFather
};
const rocky = {
name: "Rocky",
father: rockysFather
};
const rockyClone = esclone(rocky);
Example use in ES5:
var esclone = require("esclone")
var foo = new String("abcd")
var fooClone = esclone.default(foo)
console.log(fooClone)
console.log(foo === fooClone)
2. deep copy
npm install deep-copy https://www.npmjs.com/package/deep-copy
Example:
var dcopy = require('deep-copy')
// deep copy object
var copy = dcopy({a: {b: [{c: 5}]}})
// deep copy array
var copy = dcopy([1, 2, {a: {b: 5}}])
3. clone-deep
$ npm install --save clone-deep https://www.npmjs.com/package/clone-deep
Example:
var cloneDeep = require('clone-deep');
var obj = {a: 'b'};
var arr = [obj];
var copy = cloneDeep(arr);
obj.c = 'd';
console.log(copy);
//=> [{a: 'b'}]
console.log(arr);

- 1,455
- 1
- 11
- 16
function clone(obj) {
var copy;
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
use the following method instead of JSON.parse(JSON.stringify(obj))
because
it is slower than the following method

- 54
- 4
How about merging the keys of the object with its values?
function deepClone(o) {
var keys = Object.keys(o);
var values = Object.values(o);
var clone = {};
keys.forEach(function(key, i) {
clone[key] = typeof values[i] == 'object' ? Object.create(values[i]) : values[i];
});
return clone;
}
Note: This method doesn't necessarily make shallow copies, but it only copies with the depth of one inner-object, meaning that when you are given something like {a: {b: {c: null}}}
, it will only clone the objects that are directly inside of them, so deepClone(a.b).c
is technically a reference to a.b.c
, while deepClone(a).b
is a clone, not a reference.

- 2,505
- 2
- 24
- 43
-
Not a deep clone. Only does one layer of depth. Also doesn't work for arrays or anything with the value `null` due to incorrect typeof checking. – zkldi Nov 08 '22 at 14:53
Cloning an object using today's JavaScript: ECMAScript 2015 (formerly known as ECMAScript 6)
var original = {a: 1};
// Method 1: New object with original assigned.
var copy1 = Object.assign({}, original);
// Method 2: New object with spread operator assignment.
var copy2 = {...original};
Old browsers may not support ECMAScript 2015. A common solution is to use a JavaScript-to-JavaScript compiler like Babel to output an ECMAScript 5 version of your JavaScript code.
As pointed out by @jim-hall, this is only a shallow copy. Properties of properties are copied as a reference: changing one would change the value in the other object/instance.

- 494
- 5
- 13

- 3,890
- 4
- 24
- 30
-
34This doesn't address deep merges. https://gist.github.com/jimbol/5d5a3e3875c34abcf60a – Jim Hall Mar 25 '16 at 18:10
-
25Wow, this answer is so wrong. Both your methods do a shallow copy of one level. Anyone looking at this answer, move on. – basickarl Apr 21 '17 at 09:59