Simple trick to deep clone a nested data structure in JavaScript

A longer time ago I was working on a Node.js application with Ractive.js as front end library. Naturally in our front end we had complex data structures to represent the data on the screen.

To implement a search I had to create a clone of an array which had objects as its elements. Similar to this:

var macbook = {
company: 'apple',
price: 1000
};
var notebook = {
company: 'lenovo',
price: 500
};
var products = [macbook, notebook];

A standard way to create a duplication of an array would be using Array.prototype.slice(). But sadly in this case:

var products_clone = products.slice();
products_clone[0].company = 'microsoft';
// prints: '{ company: 'microsoft', price: 1000 }'
console.log(products[0]);

The array itself is a clone but the elements of the array which are objects are still referencing the same object.

After thinking for a while how to easily deep clone a structure like this I found a funny but simple solution:

// turns the data structure into a string and back into an array
var products_clone = JSON.parse(JSON.stringify(products));
products_clone[0].company = 'microsoft';
// prints: '{ company: 'apple', price: 1000 }'
console.log(products[0]);

Naturally this only works if the objects don’t have methods defined. The following would not work using the JSON conversion.

var macbook = {
company: 'apple',
price: 1000,
costs: function() {
console.log('costs: ' + price);
}
}
var notebook = {
company: 'lenovo',
price: 500
}
var products = [macbook, notebook]
var products_clone = JSON.parse(JSON.stringify(products));
// TypeError: products_clone[0].costs is not a function
products_clone[0].costs();

During the JSON conversion the costs method gets lost.

For the sake of completeness you could simply create a deep clone in this case using the lodash utility library:

var _ = require('lodash');
// create objects and array like above
var products_clone = _.cloneDeep(products);
// prints: 'costs: 1000'
products_clone[0].costs();