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