Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cloning: what's the fastest alternative to JSON.parse(JSON.stringify(x))?

Tags:

javascript

What's the fastest alternative to

JSON.parse(JSON.stringify(x)) 

There must be a nicer/built-in way to perform a deep clone on objects/arrays, but I haven't found it yet.

Any ideas?

like image 689
fadedbee Avatar asked Oct 27 '11 11:10

fadedbee


People also ask

What is the fastest JSON parser?

We released simdjson 0.3: the fastest JSON parser in the world is even better! Last year (2019), we released the simjson library. It is a C++ library available under a liberal license (Apache) that can parse JSON documents very fast.

What we can use instead of JSON Stringify?

You should use the library json2. js . It is the basis for the standard JSON. stringify(...) that some browsers include natively.

What is the most efficient way to deep clone an object in JavaScript?

According to the benchmark test, the fastest way to deep clone an object in javascript is to use lodash deep clone function since Object. assign supports only shallow copy.

Is JSON parse and Stringify slow?

parse: 702 ms. Clearly JSON. parse is the slowest of them, and by some margin.


1 Answers

No, there is no build in way to deep clone objects.

And deep cloning is a difficult and edgey thing to deal with.

Lets assume that a method deepClone(a) should return a "deep clone" of b.

Now a "deep clone" is an object with the same [[Prototype]] and having all the own properties cloned over.

For each clone property that is cloned over, if that has own properties that can be cloned over then do so, recursively.

Of course were keeping the meta data attached to properties like [[Writable]] and [[Enumerable]] in-tact. And we will just return the thing if it's not an object.

var deepClone = function (obj) {     try {         var names = Object.getOwnPropertyNames(obj);     } catch (e) {         if (e.message.indexOf("not an object") > -1) {             // is not object             return obj;         }         }     var proto = Object.getPrototypeOf(obj);     var clone = Object.create(proto);     names.forEach(function (name) {         var pd = Object.getOwnPropertyDescriptor(obj, name);         if (pd.value) {             pd.value = deepClone(pd.value);         }         Object.defineProperty(clone, name, pd);     });     return clone; }; 

This will fail for a lot of edge cases.

Live Example

As you can see you can't deep clone objects generally without breaking their special properties (like .length in array). To fix that you have to treat Array seperately, and then treat every special object seperately.

What do you expect to happen when you do deepClone(document.getElementById("foobar")) ?

As an aside, shallow clones are easy.

Object.getOwnPropertyDescriptors = function (obj) {     var ret = {};     Object.getOwnPropertyNames(obj).forEach(function (name) {         ret[name] = Object.getOwnPropertyDescriptor(obj, name);     });     return ret; };  var shallowClone = function (obj) {     return Object.create(         Object.getPrototypeOf(obj),         Object.getOwnPropertyDescriptors(obj)     ); }; 
like image 149
Raynos Avatar answered Oct 16 '22 08:10

Raynos