Tutorial :How do I correctly clone a JavaScript object?



Question:

I have an object, x. I'd like to copy it as object y, such that changes to y do not modify x. I realized that copying objects derived from built-in JavaScript objects will result in extra, unwanted properties. This isn't a problem, since I'm copying one of my own, literal-constructed objects.

How do I correctly clone a JavaScript object?


Solution:1

Updated answer

Just use Object.assign() as suggested here


Outdated answer

To do this for any object in JavaScript will not be simple or straightforward. You will run into the problem of erroneously picking up attributes from the object's prototype that should be left in the prototype and not copied to the new instance. If, for instance, you are adding a clone method to Object.prototype, as some answers depict, you will need to explicitly skip that attribute. But what if there are other additional methods added to Object.prototype, or other intermediate prototypes, that you don't know about? In that case, you will copy attributes you shouldn't, so you need to detect unforeseen, non-local attributes with the hasOwnProperty method.

In addition to non-enumerable attributes, you'll encounter a tougher problem when you try to copy objects that have hidden properties. For example, prototype is a hidden property of a function. Also, an object's prototype is referenced with the attribute __proto__, which is also hidden, and will not be copied by a for/in loop iterating over the source object's attributes. I think __proto__ might be specific to Firefox's JavaScript interpreter and it may be something different in other browsers, but you get the picture. Not everything is enumerable. You can copy a hidden attribute if you know its name, but I don't know of any way to discover it automatically.

Yet another snag in the quest for an elegant solution is the problem of setting up the prototype inheritance correctly. If your source object's prototype is Object, then simply creating a new general object with {} will work, but if the source's prototype is some descendant of Object, then you are going to be missing the additional members from that prototype which you skipped using the hasOwnProperty filter, or which were in the prototype, but weren't enumerable in the first place. One solution might be to call the source object's constructor property to get the initial copy object and then copy over the attributes, but then you still will not get non-enumerable attributes. For example, a Date object stores its data as a hidden member:

function clone(obj) {      if (null == obj || "object" != typeof obj) return obj;      var copy = obj.constructor();      for (var attr in obj) {          if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];      }      return copy;  }    var d1 = new Date();    /* Executes function after 5 seconds. */  setTimeout(function(){      var d2 = clone(d1);      alert("d1 = " + d1.toString() + "\nd2 = " + d2.toString());  }, 5000);  

The date string for d1 will be 5 seconds behind that of d2. A way to make one Date the same as another is by calling the setTime method, but that is specific to the Date class. I don't think there is a bullet-proof general solution to this problem, though I would be happy to be wrong!

When I had to implement general deep copying I ended up compromising by assuming that I would only need to copy a plain Object, Array, Date, String, Number, or Boolean. The last 3 types are immutable, so I could perform a shallow copy and not worry about it changing. I further assumed that any elements contained in Object or Array would also be one of the 6 simple types in that list. This can be accomplished with code like the following:

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.");  }  

The above function will work adequately for the 6 simple types I mentioned, as long as the data in the objects and arrays form a tree structure. That is, there isn't more than one reference to the same data in the object. For example:

// This would be cloneable:  var tree = {      "left"  : { "left" : null, "right" : null, "data" : 3 },      "right" : null,      "data"  : 8  };    // This would kind-of work, but you would get 2 copies of the   // inner node instead of 2 references to the same copy  var directedAcylicGraph = {      "left"  : { "left" : null, "right" : null, "data" : 3 },      "data"  : 8  };  directedAcyclicGraph["right"] = directedAcyclicGraph["left"];    // Cloning this would cause a stack overflow due to infinite recursion:  var cyclicGraph = {      "left"  : { "left" : null, "right" : null, "data" : 3 },      "data"  : 8  };  cyclicGraph["right"] = cyclicGraph;  

It will not be able to handle any JavaScript object, but it may be sufficient for many purposes as long as you don't assume that it will just work for anything you throw at it.


Solution:2

With jQuery, you can shallow copy with extend:

var copiedObject = jQuery.extend({}, originalObject)  

subsequent changes to the copiedObject will not affect the originalObject, and vice versa.

Or to make a deep copy:

var copiedObject = jQuery.extend(true, {}, originalObject)  


Solution:3

If you do not use functions within your object, a very simple one liner can be the following:

var cloneOfA = JSON.parse(JSON.stringify(a));  

This works for all kind of objects containing objects, arrays, strings, booleans and numbers.

See also this article about the structured clone algorithm of browsers which is used when posting messages to and from a worker. It also contains a function for deep cloning.


Solution:4

In ECMAScript 6 there is Object.assign method, which copies values of all enumerable own properties from one object to another. For example:

var x = {myProp: "value"};  var y = Object.assign({}, x);   

But be aware that nested objects are still copied as reference.


Solution:5

There are many answers, but none that mentions Object.create from ECMAScript 5, which admittedly does not give you an exact copy, but sets the source as the prototype of the new object.

Thus, this is not an exact answer to the question, but it is a one-line solution and thus elegant. And it works best for 2 cases:

  1. Where such inheritance is useful (duh!)
  2. Where the source object won't be modified, thus making the relation between the 2 objects a non issue.

Example:

var foo = { a : 1 };  var bar = Object.create(foo);  foo.a; // 1  bar.a; // 1  foo.a = 2;  bar.a; // 2 - prototype changed  bar.a = 3;  foo.a; // Still 2, since setting bar.a makes it an "own" property  

Why do I consider this solution to be superior? It's native, thus no looping, no recursion. However, older browsers will need a polyfill.


Solution:6

An elegant way to clone a Javascript 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.

Read more...

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


Solution:7

Per MDN:

  • If you want shallow copy, use Object.assign({}, a)
  • For "deep" copy, use JSON.parse(JSON.stringify(a))

There is no need for external libraries but you need to check browser compatibility first.


Solution:8

If you're okay with a shallow copy, the underscore.js library has a clone method.

y = _.clone(x);  

or you can extend it like

copiedObject = _.extend({},originalObject);  


Solution:9

There are several issues with most solutions on the internet. So I decided to make a follow-up, which includes, why the accepted answer shouldn't be accepted.

starting situation

I want to deep-copy a Javascript Object with all of its children and their children and so on. But since I'm not kind of a normal developer, my Object has normal properties, circular structures and even nested objects.

So let's create a circular structure and a nested object first.

function Circ() {      this.me = this;  }    function Nested(y) {      this.y = y;  }  

Let's bring everything together in an Object named a.

var a = {      x: 'a',      circ: new Circ(),      nested: new Nested('a')  };  

Next, we want to copy a into a variable named b and mutate it.

var b = a;    b.x = 'b';  b.nested.y = 'b';  

You know what happened here because if not you wouldn't even land on this great question.

console.log(a, b);    a --> Object {      x: "b",      circ: Circ {          me: Circ { ... }      },      nested: Nested {          y: "b"      }  }    b --> Object {      x: "b",      circ: Circ {          me: Circ { ... }      },      nested: Nested {          y: "b"      }  }  

Now let's find a solution.

JSON

The first attempt I tried was using JSON.

var b = JSON.parse( JSON.stringify( a ) );    b.x = 'b';  b.nested.y = 'b';  

Don't waste too much time on it, you'll get TypeError: Converting circular structure to JSON.

Recursive copy (the accepted "answer")

Let's have a look at the accepted answer.

function cloneSO(obj) {      // Handle the 3 simple types, and null or undefined      if (null == obj || "object" != typeof obj) return obj;        // Handle Date      if (obj instanceof Date) {          var copy = new Date();          copy.setTime(obj.getTime());          return copy;      }        // Handle Array      if (obj instanceof Array) {          var copy = [];          for (var i = 0, len = obj.length; i < len; i++) {              copy[i] = cloneSO(obj[i]);          }          return copy;      }        // Handle Object      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! Its type isn't supported.");  }  

Looks good, heh? It's a recursive copy of the object and handles other types as well, like Date, but that wasn't a requirement.

var b = cloneSO(a);    b.x = 'b';  b.nested.y = 'b';  

Recursion and circular structures doesn't work well together... RangeError: Maximum call stack size exceeded

native solution

After arguing with my co-worker, my boss asked us what happened, and he found a simple solution after some googling. It's called Object.create.

var b = Object.create(a);    b.x = 'b';  b.nested.y = 'b';  

This solution was added to Javascript some time ago and even handles circular structure.

console.log(a, b);    a --> Object {      x: "a",      circ: Circ {          me: Circ { ... }      },      nested: Nested {          y: "b"      }  }    b --> Object {      x: "b",      circ: Circ {          me: Circ { ... }      },      nested: Nested {          y: "b"      }  }  

... and you see, it didn't work with the nested structure inside.

polyfill for the native solution

There's a polyfill for Object.create in the older browser just like the IE 8. It's something like recommended by Mozilla, and of course, it's not perfect and results in the same problem as the native solution.

function F() {};  function clonePF(o) {      F.prototype = o;      return new F();  }    var b = clonePF(a);    b.x = 'b';  b.nested.y = 'b';  

I've put F outside the scope so we can have a look at what instanceof tells us.

console.log(a, b);    a --> Object {      x: "a",      circ: Circ {          me: Circ { ... }      },      nested: Nested {          y: "b"      }  }    b --> F {      x: "b",      circ: Circ {          me: Circ { ... }      },      nested: Nested {          y: "b"      }  }    console.log(typeof a, typeof b);    a --> object  b --> object    console.log(a instanceof Object, b instanceof Object);    a --> true  b --> true    console.log(a instanceof F, b instanceof F);    a --> false  b --> true  

Same problem as the native solution, but a little bit worse output.

the better (but not perfect) solution

When digging around, I found a similar question (In Javascript, when performing a deep copy, how do I avoid a cycle, due to a property being "this"?) to this one, but with a way better solution.

function cloneDR(o) {      const gdcc = "__getDeepCircularCopy__";      if (o !== Object(o)) {          return o; // primitive value      }        var set = gdcc in o,          cache = o[gdcc],          result;      if (set && typeof cache == "function") {          return cache();      }      // else      o[gdcc] = function() { return result; }; // overwrite      if (o instanceof Array) {          result = [];          for (var i=0; i<o.length; i++) {              result[i] = cloneDR(o[i]);          }      } else {          result = {};          for (var prop in o)              if (prop != gdcc)                  result[prop] = cloneDR(o[prop]);              else if (set)                  result[prop] = cloneDR(cache);      }      if (set) {          o[gdcc] = cache; // reset      } else {          delete o[gdcc]; // unset again      }      return result;  }    var b = cloneDR(a);    b.x = 'b';  b.nested.y = 'b';  

And let's have a look at the output...

console.log(a, b);    a --> Object {      x: "a",      circ: Object {          me: Object { ... }      },      nested: Object {          y: "a"      }  }    b --> Object {      x: "b",      circ: Object {          me: Object { ... }      },      nested: Object {          y: "b"      }  }    console.log(typeof a, typeof b);    a --> object  b --> object    console.log(a instanceof Object, b instanceof Object);    a --> true  b --> true    console.log(a instanceof F, b instanceof F);    a --> false  b --> false  

The requirements are matched, but there are still some smaller issues, including changing the instance of nested and circ to Object.

The structure of trees that share a leaf won't be copied, they will become two independent leaves:

        [Object]                     [Object]           /    \                       /    \          /      \                     /      \        |/_      _\|                 |/_      _\|      [Object]    [Object]   ===>  [Object]    [Object]         \        /                 |           |          \      /                  |           |          _\|  |/_                 \|/         \|/          [Object]               [Object]    [Object]  

conclusion

The last solution using recursion and a cache, may not be the best, but it's a real deep-copy of the object. It handles simple properties, circular structures and nested object, but it will mess up the instance of them while cloning.

http://jsfiddle.net/einfallstoll/N4mr2/


Solution:10

One particularly inelegant solution is to use JSON encoding to make deep copies of objects that do not have member methods. The methodology is to JSON encode your target object, then by decoding it, you get the copy you are looking for. You can decode as many times as you want to make as many copies as you need.

Of course, functions do not belong in JSON, so this only works for objects without member methods.

This methodology was perfect for my use case, since I'm storing JSON blobs in a key-value store, and when they are exposed as objects in a JavaScript API, each object actually contains a copy of the original state of the object so we can calculate the delta after the caller has mutated the exposed object.

var object1 = {key:"value"};  var object2 = object1;    object2 = JSON.stringify(object1);  object2 = JSON.parse(object2);    object2.key = "a change";  console.log(object1);// returns value  


Solution:11

For those using AngularJS, there is also direct method for cloning or extending of the objects in this library.

var destination = angular.copy(source);  

or

angular.copy(source, destination);  

More in angular.copy documentation...


Solution:12

You can simply use a spread property to copy an object without references. But be careful (see comments), the 'copy' is just on the lowest object/array level. Nested properties are still references!


Complete clone:

let x = {a: 'value1'}  let x2 = {...x}    // => mutate without references:    x2.a = 'value2'  console.log(x.a)    // => 'value1'  

Clone with references on second level:

const y = {a: {b: 'value3'}}  const y2 = {...y}    // => nested object is still a references:    y2.a.b = 'value4'  console.log(y.a.b)    // => 'value4'  

JavaScript actually does not support deep clones natively. Use an utility function. For example Ramda:

http://ramdajs.com/docs/#clone


Solution:13

OK, imagine you have this object below and you want to clone it:

let obj = {a:1, b:2, c:3}; //ES6  

or

var obj = {a:1, b:2, c:3}; //ES5  

The answer is mainly depeneds on which ECMAscript you using, in ES6+, you can simply use Object.assign to do the clone:

let cloned = Object.assign({}, obj); //new {a:1, b:2, c:3};  

or using spread operator like this:

let cloned = {...obj}; //new {a:1, b:2, c:3};  

But if you using ES5, you can use few methods, but the JSON.stringify, just make sure you not using for a big chunk of data to copy, but it could be one line handy way in many cases, something like this:

let cloned = JSON.parse(JSON.stringify(obj));   //new {a:1, b:2, c:3};, can be handy, but avoid using on big chunk of data over and over  


Solution:14

A.Levy's answer is almost complete, here is my little contribution: there is a way how to handle recursive references, see this line

if(this[attr]==this) copy[attr] = copy;

If the object is XML DOM element, we must use cloneNode instead

if(this.cloneNode) return this.cloneNode(true);

Inspired by A.Levy's exhaustive study and Calvin's prototyping approach, I offer this solution:

Object.prototype.clone = function() {    if(this.cloneNode) return this.cloneNode(true);    var copy = this instanceof Array ? [] : {};    for(var attr in this) {      if(typeof this[attr] == "function" || this[attr]==null || !this[attr].clone)        copy[attr] = this[attr];      else if(this[attr]==this) copy[attr] = copy;      else copy[attr] = this[attr].clone();    }    return copy;  }    Date.prototype.clone = function() {    var copy = new Date();    copy.setTime(this.getTime());    return copy;  }    Number.prototype.clone =   Boolean.prototype.clone =  String.prototype.clone = function() {    return this;  }  

See also Andy Burke's note in the answers.


Solution:15

From this article: How to copy arrays and objects in Javascript by Brian Huisman:

Object.prototype.clone = function() {    var newObj = (this instanceof Array) ? [] : {};    for (var i in this) {      if (i == 'clone') continue;      if (this[i] && typeof this[i] == "object") {        newObj[i] = this[i].clone();      } else newObj[i] = this[i]    } return newObj;  };  


Solution:16

In ES-6 you can simply use Object.assign(...). Ex:

let obj = {person: 'Thor Odinson'};  let clone = Object.assign({}, obj);  

A good reference is here: https://googlechrome.github.io/samples/object-assign-es6/


Solution:17

Here is a function you can use.

function clone(obj) {      if(obj == null || typeof(obj) != 'object')          return obj;          var temp = new obj.constructor();       for(var key in obj)          temp[key] = clone(obj[key]);          return temp;  }  


Solution:18

You can clone an object and remove any reference from the previous one using a single line of code. Simply do:

var obj1 = { text: 'moo1' };  var obj2 = Object.create(obj1); // Creates a new clone without references    obj2.text = 'moo2'; // Only updates obj2's text property    console.log(obj1, obj2); // Outputs: obj1: {text:'moo1'}, obj2: {text:'moo2'}  

For browsers / engines that do not currently support Object.create you can use this polyfill:

// Polyfill Object.create if it does not exist  if (!Object.create) {      Object.create = function (o) {          var F = function () {};          F.prototype = o;          return new F();      };  }  


Solution:19

New answer to an old question! If you have the pleasure of having using ECMAScript 2016 (ES6) with Spread Syntax, it's easy.

keepMeTheSame = {first: "Me!", second: "You!"};  cloned = {...keepMeTheSame}  

This provides a clean method for a shallow copy of an object. Making a deep copy, meaning makign a new copy of every value in every recursively nested object, requires on of the heavier solutions above.

JavaScript keeps evolving.


Solution:20

Using Lodash:

var y = _.clone(x, true);  


Solution:21

Interested in cloning simple objects :

JSON.parse(JSON.stringify(json_original));

Source : How to copy JavaScript object to new variable NOT by reference?


Solution:22

let clone = Object.assign( Object.create( Object.getPrototypeOf(obj)), obj)  

ES6 solution if you want to (shallow) clone a class instance and not just a property object.


Solution:23

Jan Turoň's answer above is very close, and may be the best to use in a browser due to compatibility issues, but it will potentially cause some strange enumeration issues. For instance, executing:

for ( var i in someArray ) { ... }  

Will assign the clone() method to i after iterating through the elements of the array. Here's an adaptation that avoids the enumeration and works with node.js:

Object.defineProperty( Object.prototype, "clone", {      value: function() {          if ( this.cloneNode )          {              return this.cloneNode( true );          }            var copy = this instanceof Array ? [] : {};          for( var attr in this )          {              if ( typeof this[ attr ] == "function" || this[ attr ] == null || !this[ attr ].clone )              {                  copy[ attr ] = this[ attr ];              }              else if ( this[ attr ] == this )              {                  copy[ attr ] = copy;              }              else              {                  copy[ attr ] = this[ attr ].clone();              }          }          return copy;      }  });    Object.defineProperty( Date.prototype, "clone", {      value: function() {          var copy = new Date();          copy.setTime( this.getTime() );          return copy;      }  });    Object.defineProperty( Number.prototype, "clone", { value: function() { return this; } } );  Object.defineProperty( Boolean.prototype, "clone", { value: function() { return this; } } );  Object.defineProperty( String.prototype, "clone", { value: function() { return this; } } );  

This avoids making the clone() method enumerable because defineProperty() defaults enumerable to false.


Solution:24

This is an adaptation of A. Levy's code to also handle the cloning of functions and multiple/cyclic references - what this means is that if two properties in the tree which is cloned are references of the same object, the cloned object tree will have these properties point to one and the same clone of the referenced object. This also solves the case of cyclic dependencies which, if left unhandled, leads to an infinite loop. The complexity of the algorithm is O(n)

function clone(obj){      var clonedObjectsArray = [];      var originalObjectsArray = []; //used to remove the unique ids when finished      var next_objid = 0;        function objectId(obj) {          if (obj == null) return null;          if (obj.__obj_id == undefined){              obj.__obj_id = next_objid++;              originalObjectsArray[obj.__obj_id] = obj;          }          return obj.__obj_id;      }        function cloneRecursive(obj) {          if (null == obj || typeof obj == "string" || typeof obj == "number" || typeof obj == "boolean") return obj;            // Handle Date          if (obj instanceof Date) {              var copy = new Date();              copy.setTime(obj.getTime());              return copy;          }            // Handle Array          if (obj instanceof Array) {              var copy = [];              for (var i = 0; i < obj.length; ++i) {                  copy[i] = cloneRecursive(obj[i]);              }              return copy;          }            // Handle Object          if (obj instanceof Object) {              if (clonedObjectsArray[objectId(obj)] != undefined)                  return clonedObjectsArray[objectId(obj)];                var copy;              if (obj instanceof Function)//Handle Function                  copy = function(){return obj.apply(this, arguments);};              else                  copy = {};                clonedObjectsArray[objectId(obj)] = copy;                for (var attr in obj)                  if (attr != "__obj_id" && obj.hasOwnProperty(attr))                      copy[attr] = cloneRecursive(obj[attr]);                                 return copy;          }                     throw new Error("Unable to copy obj! Its type isn't supported.");      }      var cloneObj = cloneRecursive(obj);            //remove the unique ids      for (var i = 0; i < originalObjectsArray.length; i++)      {          delete originalObjectsArray[i].__obj_id;      };        return cloneObj;  }  

Some quick tests

var auxobj = {      prop1 : "prop1 aux val",       prop2 : ["prop2 item1", "prop2 item2"]      };    var obj = new Object();  obj.prop1 = "prop1_value";  obj.prop2 = [auxobj, auxobj, "some extra val", undefined];  obj.nr = 3465;  obj.bool = true;    obj.f1 = function (){      this.prop1 = "prop1 val changed by f1";  };    objclone = clone(obj);    //some tests i've made  console.log("test number, boolean and string cloning: " + (objclone.prop1 == obj.prop1 && objclone.nr == obj.nr && objclone.bool == obj.bool));    objclone.f1();  console.log("test function cloning 1: " + (objclone.prop1 == 'prop1 val changed by f1'));  objclone.f1.prop = 'some prop';  console.log("test function cloning 2: " + (obj.f1.prop == undefined));    objclone.prop2[0].prop1 = "prop1 aux val NEW";  console.log("test multiple references cloning 1: " + (objclone.prop2[1].prop1 == objclone.prop2[0].prop1));  console.log("test multiple references cloning 2: " + (objclone.prop2[1].prop1 != obj.prop2[0].prop1));  


Solution:25

I just wanted to add to all the Object.create solutions in this post, that this does not work in the desired way with nodejs.

In Firefox the result of

var a = {"test":"test"};  var b = Object.create(a);  console.log(b);´  

is

{test:"test"}.

In nodejs it is

{}  


Solution:26

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


Solution:27

Since mindeavor stated that the object to be cloned is a 'literal-constructed' object, a solution might be to simply generate the object multiple times rather than cloning an instance of the object:

function createMyObject()  {      var myObject =      {          ...      };      return myObject;  }    var myObjectInstance1 = createMyObject();  var myObjectInstance2 = createMyObject();  


Solution:28

I've written my own implementation. Not sure if it counts as a better solution:

/*      a function for deep cloning objects that contains other nested objects and circular structures.      objects are stored in a 3D array, according to their length (number of properties) and their depth in the original object.                                      index (z)                                           |                                           |                                           |                                           |                                           |                                           |                      depth (x)                                           |_ _ _ _ _ _ _ _ _ _ _ _                                          /_/_/_/_/_/_/_/_/_/                                         /_/_/_/_/_/_/_/_/_/                                        /_/_/_/_/_/_/...../                                       /................./                                      /.....            /                                     /                 /                                    /------------------              object length (y)    /  */  

Following is the implementation:

function deepClone(obj) {      var depth = -1;      var arr = [];      return clone(obj, arr, depth);  }    /**   *   * @param obj source object   * @param arr 3D array to store the references to objects   * @param depth depth of the current object relative to the passed 'obj'   * @returns {*}   */  function clone(obj, arr, depth){      if (typeof obj !== "object") {          return obj;      }        var length = Object.keys(obj).length; // native method to get the number of properties in 'obj'        var result = Object.create(Object.getPrototypeOf(obj)); // inherit the prototype of the original object      if(result instanceof Array){          result.length = length;      }        depth++; // depth is increased because we entered an object here        arr[depth] = []; // this is the x-axis, each index here is the depth      arr[depth][length] = []; // this is the y-axis, each index is the length of the object (aka number of props)      // start the depth at current and go down, cyclic structures won't form on depths more than the current one      for(var x = depth; x >= 0; x--){          // loop only if the array at this depth and length already have elements          if(arr[x][length]){              for(var index = 0; index < arr[x][length].length; index++){                  if(obj === arr[x][length][index]){                      return obj;                  }              }          }      }        arr[depth][length].push(obj); // store the object in the array at the current depth and length      for (var prop in obj) {          if (obj.hasOwnProperty(prop)) result[prop] = clone(obj[prop], arr, depth);      }        return result;  }  


Solution:29

Bellow is my version of deep cloning, covering functions and with handling for circular references.

https://github.com/radsimu/UaicNlpToolkit/blob/master/Modules/GGS/GGSEngine/src/main/resources/ro/uaic/info/nlptools/ggs/engine/core/jsInitCode.js#L17


Solution:30

Consult http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#safe-passing-of-structured-data for the W3C's "Safe passing of structured data" algorithm, intended to be implemented by browsers for passing data to eg web workers. However, it has some limitations, in that it does not handle functions. See https://developer.mozilla.org/en-US/docs/DOM/The_structured_clone_algorithm for more information, including an alternative algorithm in JS which gets you part of the way there.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »