What is the best way to clone an object in node.js
e.g. I want to avoid the situation where:
var obj1 = {x: 5, y:5};
var obj2 = obj1;
obj2.x = 6;
con
var obj2 = JSON.parse(JSON.stringify(obj1));
There is another library lodash, it has clone and cloneDeep.
clone
will clone your object but not create a new instance for non-primitive values, instead it will use the referrence to the original object
cloneDeep
will create literally new objects without having any referrence to the original object, so it more safe when you have to change the object afterwards.
You can also use this clone library to deep clone objects.
npm install --save clone
const clone = require('clone');
const clonedObject = clone(sourceObject);
There is no built-in way to do a real clone (deep copy) of an object in node.js. There are some tricky edge cases so you should definitely use a library for this. I wrote such a function for my simpleoo library. You can use the deepCopy
function without using anything else from the library (which is quite small) if you don't need it. This function supports cloning multiple data types, including arrays, dates, and regular expressions, it supports recursive references, and it also works with objects whose constructor functions have required parameters.
Here is the code:
//If Object.create isn't already defined, we just do the simple shim, without the second argument,
//since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
object_create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}
/**
* Deep copy an object (make copies of all its object properties, sub-properties, etc.)
* An improved version of http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
* that doesn't break if the constructor has required parameters
*
* It also borrows some code from http://stackoverflow.com/a/11621004/560114
*/
function deepCopy = function deepCopy(src, /* INTERNAL */ _visited) {
if(src == null || typeof(src) !== 'object'){
return src;
}
// Initialize the visited objects array if needed
// This is used to detect cyclic references
if (_visited == undefined){
_visited = [];
}
// Ensure src has not already been visited
else {
var i, len = _visited.length;
for (i = 0; i < len; i++) {
// If src was already visited, don't try to copy it, just return the reference
if (src === _visited[i]) {
return src;
}
}
}
// Add this object to the visited array
_visited.push(src);
//Honor native/custom clone methods
if(typeof src.clone == 'function'){
return src.clone(true);
}
//Special cases:
//Array
if (Object.prototype.toString.call(src) == '[object Array]') {
//[].slice(0) would soft clone
ret = src.slice();
var i = ret.length;
while (i--){
ret[i] = deepCopy(ret[i], _visited);
}
return ret;
}
//Date
if (src instanceof Date) {
return new Date(src.getTime());
}
//RegExp
if (src instanceof RegExp) {
return new RegExp(src);
}
//DOM Element
if (src.nodeType && typeof src.cloneNode == 'function') {
return src.cloneNode(true);
}
//If we've reached here, we have a regular object, array, or function
//make sure the returned object has the same prototype as the original
var proto = (Object.getPrototypeOf ? Object.getPrototypeOf(src): src.__proto__);
if (!proto) {
proto = src.constructor.prototype; //this line would probably only be reached by very old browsers
}
var ret = object_create(proto);
for(var key in src){
//Note: this does NOT preserve ES5 property attributes like 'writable', 'enumerable', etc.
//For an example of how this could be modified to do so, see the singleMixin() function
ret[key] = deepCopy(src[key], _visited);
}
return ret;
};
Simple and the fastest way to clone an Object in NodeJS is to use Object.keys( obj ) method
var a = {"a": "a11", "b": "avc"};
var b;
for(var keys = Object.keys(a), l = keys.length; l; --l)
{
b[ keys[l-1] ] = a[ keys[l-1] ];
}
b.a = 0;
console.log("a: " + JSON.stringify(a)); // LOG: a: {"a":"a11","b":"avc"}
console.log("b: " + JSON.stringify(b)); // LOG: b: {"a":0,"b":"avc"}
The method Object.keys requires JavaScript 1.8.5; nodeJS v0.4.11 supports this method
but of course for nested objects need to implement recursive func
Other solution is to use native JSON (Implemented in JavaScript 1.7), but it's much slower (~10 times slower) than previous one
var a = {"a": i, "b": i*i};
var b = JSON.parse(JSON.stringify(a));
b.a = 0;
None of the answers satisfied me, several don't work or are just shallow clones, answers from @clint-harris and using JSON.parse/stringify are good but quite slow. I found a module that does deep cloning fast: https://github.com/AlexeyKupershtokh/node-v8-clone