By jschrab


2008-09-23 16:26:09 8 Comments

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.

30 comments

@John Resig 2008-09-23 18:09:37

Native deep cloning

It's called "structured cloning", works experimentally in Node 11 and later, and hopefully will land in browsers. See this answer for more details.

Fast cloning with data loss - JSON.parse/stringify

If you do not use Dates, 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,

ES6

For completeness, note that ES6 offers two shallow copy mechanisms: Object.assign() and the spread operator.

@Rune FS 2013-03-27 08:16:19

@ThiefMaster github.com/jquery/jquery/blob/master/src/core.js at line 276 (there's a bit of code that does something else but the code for "how to do this in JS" is there :)

@Alex W 2013-04-11 14:24:13

Here's the JS code behind the jQuery deep copy, for anyone interested: github.com/jquery/jquery/blob/master/src/core.js#L265-327

@Jon Jaques 2014-01-09 22:40:49

Since there seems to be some contention around using jQuery, thought I would mention that I've extracted the extend functionality out to a standalone script: gist.github.com/jonjaques/3036701

@John Resig 2014-01-21 03:37:38

Woah! Just to be super-clear: no idea why this response was picked as the right answer, this was a reply to responses given below: stackoverflow.com/a/122190/6524 (which was recommending .clone(), which is not the right code to be using in this context). Unfortunately this question has gone through so many revisions the original discussion is no longer even apparent! Please just follow Corban's advice and write a loop or copy the properties directly over to a new object, if you care about speed. Or test it out for yourself!

@albanx 2014-02-28 17:29:51

If my objects has a reference to a dom element (let say obj.div = document.getElementById('id') ), does this also clone the dom element and puts it on the document?

@Octopus 2014-05-14 04:56:29

A non-jQuery equivalent of this would be var newobj = eval(oldobj.toSource()).

@RobG 2014-08-15 23:48:43

@albanx—the short answer is no. If you have a question, ask it as a question. Posting it as a comment to an old question that is now irrelevant is unlikely to be helpful. To clone a DOM element use its cloneNode method. To put it in the document, use insertBefore or appendChild or one of the other insertion or replacement methods.

@albanx 2014-08-17 07:40:40

@RobG I work with javascript complex object with reference to dom, and a clone of them will clone only the reference and not the dom element obviously. I know very well the cloneNode and company jquery functions and the comment it is not irrelevant, is just a completion to the question.

@Camilo Martin 2014-09-22 00:21:47

@albanx No, you were asking a question in the comments of an answer, which is already frowned upon, and it wasn't any sort of "completion to the question", you were just drawing attention to your own off-topic problem, which gladly for you was met with condescendence from RobG, which you even reply in a pedantic manner ("I know very well the cloneNode and company"), despite being clear by your question (and response) that you are at a novice level with javascript.

@albanx 2014-09-22 14:00:13

@CamiloMartin No camilo, my question is just a point of clarification, what does that clone ( it does not clone referenced objects). Should be clear that this clone only primitive properties of an object. so you and robg think that I should open a new question like "does the reply of this question also satisfy my question?".

@Camilo Martin 2014-09-23 01:32:39

@albanx You asked if .clone() will insert new objects in the DOM. That's a totally off-topic new question and yes, you should open a new question since this isn't a forum but a Q&A site. (Not that I encourage hijacking forum threads either.)

@gphilip 2015-01-22 08:30:39

This is a JavaScript question (no mention of jQuery).

@Awesomeness01 2015-04-30 02:22:57

How would one do this without using jQuery?

@bearoff 2015-06-24 13:27:22

According to the documentation for extend(), deep copy makes sense only for real merges of objects, and has no sense when using extend() to just clone an object.

@hehe 2015-08-19 07:38:38

This is the very good method, but I have a problem with this because it does NOT convert array properly. it changed array into objects with property names 0,1,2... Therefore I end up using JSON.parse(JSON.stringify(data)) which worked perfectly for me

@lepe 2015-10-20 04:02:31

Be aware that this method will not preserve setters and getters

@satJ 2015-10-27 16:31:05

This won't work if the object has cyclic properties. For such cases, if you want to deep copy, use either angular.copy or lodash's _.cloneDeep

@Twifty 2016-10-09 16:57:03

The question states javascript in both the title and body. It mentions nothing of jQuery. So, why is a jQuery answer so highly voted?

@HoldOffHunger 2017-08-15 13:46:07

@John Resig: That approach fails when your Object contains any type of data that is more complicated than a scalar.

@Jack Giffin 2018-04-07 00:20:49

I took a wee bitty peep at the source code (code.jquery.com/jquery-3.3.1.js)... disgusting. Simply vomit-inducing wretched garbage. Do not use jQuery. Ever.

@Ofek Shilon 2019-04-22 21:52:35

Note this code is a direct security vulnerability in jQuery versions prior to March 2019: snyk.io/blog/…

@Grault 2019-05-07 19:56:55

The original date of this answer is obscured by the community wiki, but it was 2008. Also, despite fashion trends jQuery is still a very good tool. In my admittedly limited time available for exploration, I haven't seen anything compare with it.

@Derk Jan Speelman 2019-08-28 08:29:46

@Grault NPM packages

@Ankur Kedia 2019-08-03 16:36:52

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;
  }
}

@Ian 2019-08-21 17:23:48

Careful... const o = {}; o.a = o; deepClone(o); -> recursion error.

@Corban Brook 2011-03-17 19:19:55

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 this 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.

Update for ES6

If you are using Javascript ES6 try this native method for cloning or shallow copy.

Object.assign({}, obj);

@rahpuser 2014-11-25 21:37:12

@trysis Object.create is not cloning the object, is using the prototype object... jsfiddle.net/rahpuser/yufzc1jt/2

@Jeremy Anderson 2015-01-10 01:23:04

I was scoping this npm module when I found this question. Great answer. I wonder if there's any feedback on that module, though? I glanced at the source and it seems alright. I especially like this quote: "copies the ES5 descriptor of every property that Object.getOwnPropertyDescriptor() returns".

@Karlen Kishmiryan 2015-05-29 09:52:16

This method will also remove the keys from your object, which have functions as their values, because the JSON doesn't support functions.

@dnlgmzddr 2015-07-30 21:37:10

Also keep in mind that using JSON.parse(JSON.stringify(obj)) on Date Objects will also convert the date back to UTC in the string representation in the ISO8601 format.

@datacarl 2015-09-30 19:45:55

JSON.stringify doesnt convert String or Function since they are not valid JSON. So {type: String, value: 123} would become {"value": 123} which is probably not what you want.

@Josh Mc 2015-11-28 23:09:01

@rich remer 2016-02-13 05:25:15

JSON approach also chokes on circular references.

@inferus-vv 2016-05-04 09:11:50

If you have functions as values of your object - it will NOT work for you.

@Dheeraj Bhaskar 2016-07-12 11:31:20

JSON approach will fail to copy anything that is not part of the JSON spec (json.org) including date objects, functions, circular references among others

@drhayes 2016-10-12 20:23:06

Just came by to add comment that this throws away values that are Symbol objects as well.

@tom10271 2016-10-17 07:45:08

Will JSON clone method faster than Object.assign({}, objToClone)?

@velop 2016-10-23 21:40:15

@aokaddaoc no Object.assign is much faster. I added it to the benchmark given in the answer.

@Íhor Mé 2016-11-02 16:22:44

Copying larger objects gets slightly different benchmarks than this.

@Íhor Mé 2016-11-02 18:00:45

Also, in lodash version of the benchmark cloneDeep would be correct. clone(a,true) is an inadequate comparison, as it only copies up to 2 depth levels.

@Íhor Mé 2016-11-02 18:43:27

Mind that Set doesn't get parsed by JSON.stringify

@Garrett Simpson 2016-11-03 18:00:14

@velop , Object.assign({}, objToClone) seems like it does a shallow clone though -- using it while playing around in the dev tools console, the object clone still pointed to a reference of the cloned object. So I don't think it's really applicable here.

@RobertoNovelo 2016-11-07 22:35:54

In my experience, this also replaces special chars with their UTF8 representation.

@Rico Kahler 2016-12-18 00:17:42

@Legends 2017-01-09 09:23:56

Only properties are cloned not functions, just to mention: for example: {a:function(){alert("hi");}, b: "I am b"} --> here only property b is cloned.

@Tarun 2017-01-31 12:35:54

What if obj has a circular JSON structure?

@Florian Loch 2017-03-06 17:05:44

Results completely changed with your benchmark, at least for me running a decent version of Chrome. Perhaps the answer should get updated regarding this?

@Florian Loch 2017-03-07 11:06:28

Also MDN states that Object.assign() CANNOT be used for deep cloning.

@prograhammer 2017-06-18 06:36:03

A recursive deep clone is much faster than the JSON.parse/JSON.stringify approach. See my answer here: stackoverflow.com/a/44612374/1110941

@Jenny O'Reilly 2017-11-12 16:38:06

This also removes the exact type of the object, right? So that instanceof checks no longer work on the resulting object. So this is rather a "primitive" copying than a real deep cloning.

@Andy 2017-12-04 23:31:48

it's no longer the fastest in Chrome

@loctrice 2018-02-26 16:24:34

It's also worth noting that properties with undefined values will not be included if you use stringify. This problem is what drove me to this thread, so I can't use stringify.

@Jason Goemaat 2018-07-26 04:26:38

@AlexanderF. o1 = {a:1, b:{c:2,d:[1,2,3,{e:555}]}, f: function(){console.log('Hi!')}}; o2 = Object.assign({}, o1); o2.b.c = "It was shallow..."; console.log(o1.b.c);

@Alexander F. 2018-07-26 16:39:38

@JasonGoemaat you're absolutely right! I remember playing with it a few weeks down the road and finding unexpected results. Forgot about my silly comment here though. Cannot edit anymore so will just delete it.

@Cemre 2018-08-02 22:17:07

“This one line of Javascript made FT.com 10 times slower” @adgad medium.com/ft-product-technology/…

@Raghul Shree 2019-06-06 13:46:55

You can use the Spread operator to Clone the Object in JavaScript.

// spread operator doing the concat job

let arr = [1,2,3];  let arr2 = [4,5];  arr = [...arr,...arr2]; console.log(arr); 

@Suraj Rao 2019-06-06 14:59:20

spread operator does a shallow copy not a deep one. Will not work for nested objects or objects in array

@KRIPA SHANKAR JHA 2019-05-28 06:17:12

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);

@Kamyar 2019-05-19 12:22:39

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.

@Matthieu Chavigny 2019-04-18 09:29:50

In 2019 I'm using :

deepCopy(object) {
  const getCircularReplacer = () => {
    const seen = new WeakSet();
    return (key, value) => {
      if(typeof value === 'object' && value !== null) {
        if(seen.has(value)) return;
        seen.add(value);
      }
      return value;
    };
  };
  return JSON.parse(JSON.stringify(object, getCircularReplacer()));
}

const theCopy = deepCopy(originalObject);

@Nicholas Porter 2019-04-23 03:32:57

I like this because of how it handles circular references.

@Shidersz 2019-04-16 05:33:51

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;}

@Mystical 2019-02-05 01:11:56

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.

@shakthi nagaraj 2019-02-05 13:46:15

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

How do I correctly clone a JavaScript object?

@REINSTATE MONICA -Jeremy Banks 2012-06-06 14:59:04

Structured Cloning

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: Experimental 🙂

The v8 module in Node.js currently (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: Maybe Eventually? 😐

Browsers do not currently provide a direct interface for the structured cloning algorithm, but a global structuredClone() function has been discussed in whatwg/html#793 on GitHub. As currently proposed, using it for most purposes would be as simple as:

const clone = structuredClone(original);

Unless 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();

@REINSTATE MONICA -Jeremy Banks 2013-05-06 03:11:03

@rynah I just looked through the spec again and you're right: the history.pushState() and history.replaceState() methods both synchronously set history.state to a structured clone of their first argument. A little weird, but it works. I'm updating my answer now.

@Fardin K. 2014-07-31 23:34:51

This is just so wrong! That API is not meant to be used this way.

@Justin L. 2014-08-14 18:37:25

As the guy who implemented pushState in Firefox, I feel an odd mix of pride and revulsion at this hack. Well done, guys.

@Shishir Arora 2019-07-03 20:06:56

pushState or Notification hack does not work for some object types like Function

@chandan gupta 2018-11-05 09:43:14

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;
}

@Mithun Shreevatsa 2019-09-30 08:36:40

This doesn't work for date and function

@Tính Ngô Quang 2018-08-08 08:17:31

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.)

Reference medium.com

JSBEN.CH Performance Benchmarking Playground 1~3 http://jsben.ch/KVQLd Performance Deep copying objects in JavaScript

@Roymunson 2018-08-15 20:23:28

Object.assign() does not perform a deep copy

@jcollum 2018-10-30 23:00:19

you should add benchmarks for these; that would be very helpful

@hugogogo 2019-03-24 23:54:35

when i used the "created method" on an object containing an array i was unable to use pop() or splice() on it, i don't understand why ? let data = {title:["one", "two"]}; let tmp = cloneObject(data); tmp.title.pop(); it throw: TypeError: tmp.title.pop is not a function (of course pop() works fine if i just do let tmp = data; but then i can't modify tmp without affecting data)

@shunryu111 2018-10-10 09:21:56

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"

https://codepen.io/anon/pen/OBpqNE?editors=1111

@ConroyP 2008-09-23 16:38:51

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;
}

@jschrab 2008-09-23 17:23:51

The JQuery solution will work for DOM elements but not just any Object. Mootools has the same limit. Wish they had a generic "clone" for just any object... The recursive solution should work for anything. It's probably the way to go.

@Andrew Arnott 2009-10-04 22:06:39

This function breaks if the object being cloned has a constructor that requires parameters. It seems like we can change it to "var temp = new Object()" and have it work in every case, no?

@limscoder 2011-09-14 15:53:31

Andrew, if you change it to var temp = new Object(), then your clone won't have the same prototype as the original object. Try using: 'var newProto = function(){}; newProto.prototype = obj.constructor; var temp = new newProto();'

@Matt Browne 2012-11-11 17:55:03

Similar to limscoder's answer, see my answer below on how to do this without calling the constructor: stackoverflow.com/a/13333781/560114

@virtualnobi 2013-11-11 08:34:37

For objects that contain references to sub-parts (i.e., networks of objects), this does not work: If two references point to the same sub-object, the copy contains two different copies of it. And if there are recursive references, the function will never terminate (well, at least not in the way you want it :-) For these general cases, you have to add a dictionary of objects already copied, and check whether you already copied it... Programming is complex when you use a simple language

@Peter Mortensen 2014-02-22 15:11:31

The link to Keith Deven's blog post is broken.

@Cihad Turhan 2014-03-27 10:08:22

@ConroyP this is not a healty solution in case of circular reference. jsfiddle.net/d3KcP

@Garet Claborn 2015-06-05 11:26:11

@CihadTurhan added a circular reference fix at jsfiddle.net/d3KcP/9. Note it will add a temporary property to cloned objects

@kofifus 2016-09-22 23:30:48

does not work for Event objects - constructor call fails

@Phil 2017-06-30 10:58:04

Fails for: clone({isActiveClone: false, isHijackingObjectKeysAGoodIdea: false })

@shoosh 2019-08-30 19:59:14

isActiveClone doesn't really solve all cycle problems. if an object as two references to the same object, it's going to get duplicated

@Prasanth Jaya 2018-08-23 09:40:50

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..

@Jinu Joseph Daniel 2018-07-16 07:58:04

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;
}

https://github.com/jinujd/Javascript-Deep-Clone

@Vikram K 2018-06-24 19:08:38

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.

@Taugenichts 2018-06-27 14:59:10

updating e in objClone will still update e in obj. This is still only a shallow copy. The question explicitly asks for a deep clone.

@mickro 2018-06-27 17:06:16

@Taugenichts... did you tested it? The method works perfectly. Spread_syntax Spread in object literals section

@Taugenichts 2018-06-27 17:35:46

yes, I tested it. run this code: objClone.e[4] = 5; console.log(obj.e); You will see obj.e being updated

@Lupus Ossorum 2018-06-29 21:24:06

Because 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.

@Vikram K 2018-07-10 09:29:16

Thanks a lot, [email protected] @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.

@Taugenichts 2018-09-13 15:31:36

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()." - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

@Parabolord 2018-06-19 22:06:13

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.

@Roymunson 2018-08-15 20:26:11

Can you explain what is happening in this code?

@Parabolord 2018-08-15 20:48:06

Pseudocode 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.

@zenw0lf 2019-08-24 22:30:55

Too 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.

@codeMonkey 2018-03-26 17:42:48

ES 2017 example:

let objectToCopy = someObj;
let copyOfObject = {};
Object.defineProperties(copyOfObject, Object.getOwnPropertyDescriptors(objectToCopy));
// copyOfObject will now be the same as objectToCopy

@Gurebu Bokofu 2018-06-10 03:39:53

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 and if it will be some mistake on my side, I'll vote up for your answer.

@codeMonkey 2018-06-10 03:50:01

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?

@Gurebu Bokofu 2018-06-10 03:55:32

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)

@Nikita Malyschkin 2019-01-17 06:25:42

This is not a deep copy but a shallow copy. @GurebuBokofu

@tfmontague 2014-09-18 20:10:38

Deep copy by performance: Ranked from best to worst

  • Reassignment "=" (string arrays, number arrays - only)
  • Slice (string arrays, number arrays - only)
  • Concatenation (string arrays, number arrays - only)
  • Custom function: for-loop or recursive copy
  • jQuery's $.extend
  • JSON.parse (string arrays, number arrays, object arrays - only)
  • Underscore.js's _.clone (string arrays, number arrays - only)
  • Lo-Dash's _.cloneDeep

Deep copy an array of strings or numbers (one level - no reference pointers):

When an array contains numbers and strings - functions like .slice(), .concat(), .splice(), the assignment operator "=", and Underscore.js's clone function; will make a deep copy of the array's elements.

Where reassignment has the fastest performance:

var arr1 = ['a', 'b', 'c'];
var arr2 = arr1;
arr1 = ['a', 'b', 'c'];

And .slice() has better performance than .concat(), http://jsperf.com/duplicate-array-slice-vs-concat/3

var arr1 = ['a', 'b', 'c'];  // Becomes arr1 = ['a', 'b', 'c']
var arr2a = arr1.slice(0);   // Becomes arr2a = ['a', 'b', 'c'] - deep copy
var arr2b = arr1.concat();   // Becomes arr2b = ['a', 'b', 'c'] - deep copy

Deep copy an array of objects (two or more levels - reference pointers):

var arr1 = [{object:'a'}, {object:'b'}];

Write a custom function (has faster performance than $.extend() or JSON.parse):

function copy(o) {
   var out, v, key;
   out = Array.isArray(o) ? [] : {};
   for (key in o) {
       v = o[key];
       out[key] = (typeof v === "object" && v !== null) ? copy(v) : v;
   }
   return out;
}

copy(arr1);

Use third-party utility functions:

$.extend(true, [], arr1); // Jquery Extend
JSON.parse(arr1);
_.cloneDeep(arr1); // Lo-dash

Where jQuery's $.extend has better performance:

@Nico 2016-05-09 19:56:02

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.

@Karl Morrison 2017-04-21 10:02:14

All of your examples are shallow, one level. This is not a good answer. The Question was regarding deep cloning i.e. at least two levels.

@tfmontague 2017-04-21 15:42:01

A deep copy is when an object is copied in its' entirety without the use of reference pointers to other objects. The techniques under the section "Deep copy an array of objects", such as jQuery.extend() and the custom function (which is recursive) copy objects with "at least two levels". So, no not all the examples are "one level" copies.

@josi 2018-02-01 16:53:21

I like your custom copy function, but you should exclude null values, otherwise all null values are being converted to objects, i.e.: out[key] = (typeof v === "object" && v !== null) ? copy(v) : v;

@Hossam Mourad 2018-03-19 10:49:25

@tfmontague The custom function has a bug, it convert any null value to {}. I had to refactor all of my codebase because I was depending heavily on it.

@tfmontague 2018-03-20 15:29:57

@HossamMourad - The bug was fixed by Josi on Feb1 (in the comment above), and I failed to correctly update the answer. Sorry that this bug resulted in a refactor of your code base.

@Steve Griffith 2018-02-26 04:05:16

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.

  1. JSON.parse(JSON.stringify( obj ) );

  2. Through history.state with pushState or replaceState

  3. Web Notifications API but this has the downside of asking the user for permissions.

  4. Doing your own recursive loop through the object to copy each level.

  5. 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.

@Jack Giffin 2018-04-07 00:24:58

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.

@Alireza 2017-04-03 15:37:57

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:

1) 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] = cloneSO(obj[i]);
        }
        return copy;
    }
    if (obj instanceof Object) {
        var copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = cloneSO(obj[attr]);
        }
        return copy;
    }
    throw new Error("Unable to copy obj this object.");
}

2) ES5+, using JSON.parse and JSON.stringify.

var  deepCopyObj = JSON.parse(JSON.stringify(obj));

3) AngularJs:

var  deepCopyObj = angular.copy(obj);

4) jQuery:

var deepCopyObj = jQuery.extend(true, {}, obj);

5) UnderscoreJs & Loadash:

var deepCopyObj = _.cloneDeep(obj); //latest version UndescoreJs makes shallow copy

Hope these help...

@Rogelio 2017-04-03 16:19:25

clone in underscore is not a deep clone in current version

@Alireza 2017-04-04 01:00:44

Thanks. yes as new doc for Underscore... clone_.clone(object) Create a shallow-copied clone of the provided plain object. Any nested objects or arrays will be copied by reference, not duplicated. _.clone({name: 'moe'}); => {name: 'moe'};

@jeff musk 2017-04-14 16:58:45

@Alireza obj = {copy1:'asdf', nest: {copy2: 'asdfa'}} I tried Object.assign({},obj) and find out that it copies property copy1, but does not copy copy2;

@Alireza 2017-04-15 02:21:36

@jeffmusk, the first param in Object.assign, is where you want to start and it's simply could be your first object, so do something like this instead: Object.assign(obj1, obj2);

@kba 2017-05-10 15:52:55

Object.assign does not deep copy. Example: var x = { a: { b: "c" } }; var y = Object.assign({}, x); x.a.b = "d". If this was deep copy, y.a.b would still be c, but it's now d.

@haemse 2017-07-21 10:13:53

Object.assign() only clones the first level of properties!

@pastorello 2017-08-07 16:55:40

what is cloneSO() function?

@mactive 2017-09-12 04:02:04

@pastorello cloneSO is the deepCopyObj. here is a recursive for DEEP clone

@Sophie 2019-03-08 15:21:22

angular.copy is not very performant (see here: github.com/angular/angular.js/issues/11099)

@Константин Ван 2018-01-20 20:26:35

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;
}

@Константин Ван 2019-08-27 16:13:31

Hold on, 5 upvoters, how does it work? I forgot it myself and this looks counterintuitive, now that one and half years has past.

@Dima 2010-04-28 11:16:55

// 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;
};

@opensas 2013-06-22 15:03:59

Lodash has a nice _.cloneDeep(value) method:

var objects = [{ 'a': 1 }, { 'b': 2 }];

var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false

@REINSTATE MONICA -Jeremy Banks 2016-04-07 17:23:49

I advocate deleting this and all other answers which are just one-line references to a utility library's .clone(...) method. Every major library will have them, and the repeated brief non-detailed answers aren't useful to most visitors, who won't be using that particular library.

@Rebs 2017-02-27 00:48:02

An easier way is to use _.merge({}, objA). If only lodash didn't mutate objects in the first place then the clone function wouldn't be necessary.

@Rebs 2017-02-27 00:49:11

Google searches for cloning JS objects refer to here. I'm using Lodash so this answer is relevant to me. Lets not go all "wikipedia deletionist" on answers please.

@Dan Dascalescu 2017-12-31 13:07:15

In Node 9, JSON.parse(JSON.stringify(arrayOfAbout5KFlatObjects)) is a lot faster than _.deepClone(arrayOfAbout5KFlatObjects).

@Mayur Agarwal 2017-10-11 16:02:22

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: enter image description here References: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

@Antoniossss 2018-04-26 08:30:54

its funny but when I run your tests it actually shoed me that method 1 is the slowest one

@SPG 2018-12-05 01:08:58

same as me, block 1 is the lowest!

@Julez 2017-10-15 20:01:27

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": "[email protected]"
    }
  },
  "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))

@Zen 2017-11-10 08:21:22

That's not deep clone, and you're doing it wrong.

@Julez 2018-05-29 07:15:06

please explain yourself instead of saying you're doing it wrong...

@shobhit1 2017-09-09 15:08:58

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.

@JTeam 2017-08-16 06:16:41

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);

Related Questions

Sponsored Content

38 Answered Questions

[SOLVED] How do I loop through or enumerate a JavaScript object?

46 Answered Questions

[SOLVED] How do I test for an empty JavaScript object?

  • 2009-03-25 01:39:45
  • falmp
  • 1920522 View
  • 2687 Score
  • 46 Answer
  • Tags:   javascript

36 Answered Questions

[SOLVED] What is the !! (not not) operator in JavaScript?

  • 2009-04-24 08:13:58
  • Hexagon Theory
  • 502605 View
  • 2885 Score
  • 36 Answer
  • Tags:   javascript operators

45 Answered Questions

[SOLVED] Deep cloning objects

  • 2008-09-17 00:06:27
  • NakedBrunch
  • 771220 View
  • 2119 Score
  • 45 Answer
  • Tags:   c# .net clone

74 Answered Questions

[SOLVED] What is the JavaScript version of sleep()?

  • 2009-06-04 14:41:10
  • fmsf
  • 2387301 View
  • 2090 Score
  • 74 Answer
  • Tags:   javascript sleep

20 Answered Questions

[SOLVED] Checking if a key exists in a JavaScript object?

  • 2009-07-08 13:21:32
  • Adam Ernst
  • 1794468 View
  • 2730 Score
  • 20 Answer
  • Tags:   javascript object

64 Answered Questions

[SOLVED] How do I correctly clone a JavaScript object?

27 Answered Questions

[SOLVED] What does "use strict" do in JavaScript, and what is the reasoning behind it?

41 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

38 Answered Questions

[SOLVED] Length of a JavaScript object

Sponsored Content