Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 326 Vote(s) - 3.66 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Nodejs: how to clone an object

#1
If I clone an array, I use `cloneArr = arr.slice()`

I want to know how to clone an object in nodejs.
Reply

#2
There is no native method for cloning objects. Underscore implements [`_.clone`][1] which is a shallow clone.

_.clone = function(obj) {
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};

It either slices it or extends it.

Here's [`_.extend`][2]

// extend the obj (first parameter)
_.extend = function(obj) {
// for each other parameter
each(slice.call(arguments, 1), function(source) {
// loop through all properties of the other objects
for (var prop in source) {
// if the property is not undefined then add it to the object.
if (source[prop] !== void 0) obj[prop] = source[prop];
}
});
// return the object (first parameter)
return obj;
};

Extend simply iterates through all the items and creates a new object with the items in it.

You can roll out your own naive implementation if you want

function clone(o) {
var ret = {};
Object.keys(o).forEach(function (val) {
ret[val] = o[val];
});
return ret;
}

There are good reasons to avoid deep cloning because closures cannot be cloned.

I've personally asked a question about [`deep cloning objects before`](

[To see links please register here]

) and the conclusion I came to is that you just don't do it.

My recommendation is use [`underscore`][3] and it's [`_.clone`][1] method for shallow clones

[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

Reply

#3
For utilities and classes where there is no need to squeeze every drop of performance, I often cheat and just use JSON to perform a deep copy:

function clone(a) {
return JSON.parse(JSON.stringify(a));
}

This isn't the only answer or the most elegant answer; all of the other answers should be considered for production bottlenecks. However, this is a quick and dirty solution, quite effective, and useful in most situations where I would clone a simple hash of properties.
Reply

#4
Depending on what you want to do with your cloned object you can utilize the prototypal inheritence mechanism of javascript and achieve a somewhat cloned object through:

var clonedObject = Object.create(originalObject);

Just remember that this isn't a full clone - for better or worse.

A good thing about that is that you actually haven't duplicated the object so the memory footprint will be low.

Some tricky things to remember though about this method is that iteration of properties defined in the prototype chain sometimes works a bit different and the fact that any changes to the original object will affect the cloned object as well unless that property has been set on itself also.
Reply

#5
For a shallow copy, I like to use the reduce pattern (usually in a module or such), like so:

var newObject = Object.keys(original).reduce(function (obj, item) {
obj[item] = original[item];
return obj;
},{});

Here's a jsperf for a couple of the options:

[To see links please register here]

Reply

#6
There are some Node modules out there if don't want to "roll your own". This one looks good:

[To see links please register here]


Looks like it handles all kinds of stuff, including circular references. From the [github][1] page:

> clone masters cloning objects, arrays, Date objects, and RegEx
> objects. Everything is cloned recursively, so that you can clone dates
> in arrays in objects, for example. [...] Circular references? Yep!


[1]:

[To see links please register here]

Reply

#7
I implemented a full deep copy. I believe its the best pick for a generic clone method, but it does not handle cyclical references.

# Usage example:

parent = {'prop_chain':3}
obj = Object.create(parent)
obj.a=0; obj.b=1; obj.c=2;

obj2 = copy(obj)

console.log(obj, obj.prop_chain)
// '{'a':0, 'b':1, 'c':2} 3
console.log(obj2, obj2.prop_chain)
// '{'a':0, 'b':1, 'c':2} 3

parent.prop_chain=4
obj2.a = 15

console.log(obj, obj.prop_chain)
// '{'a':0, 'b':1, 'c':2} 4
console.log(obj2, obj2.prop_chain)
// '{'a':15, 'b':1, 'c':2} 4

# The code itself:

This code copies objects with their prototypes, it also copy functions (might be useful for someone).

function copy(obj) {
// (F.prototype will hold the object prototype chain)
function F() {}
var newObj;

if(typeof obj.clone === 'function')
return obj.clone()

// To copy something that is not an object, just return it:
if(typeof obj !== 'object' && typeof obj !== 'function' || obj == null)
return obj;

if(typeof obj === 'object') {
// Copy the prototype:
newObj = {}
var proto = Object.getPrototypeOf(obj)
Object.setPrototypeOf(newObj, proto)
} else {
// If the object is a function the function evaluate it:
var aux
newObj = eval('aux='+obj.toString())
// And copy the prototype:
newObj.prototype = obj.prototype
}

// Copy the object normal properties with a deep copy:
for(var i in obj) {
if(obj.hasOwnProperty(i)) {
if(typeof obj[i] !== 'object')
newObj[i] = obj[i]
else
newObj[i] = copy(obj[i])
}
}

return newObj;
}

With this copy I can't find any difference between the original and the copied one except if the original used closures on its construction, so i think its a good implementation.

I hope it helps
Reply

#8
Old question, but there's a more elegant answer than what's been suggested so far; use the built-in utils._extend:

var extend = require("util")._extend;

var varToCopy = { test: 12345, nested: { val: 6789 } };

var copiedObject = extend({}, varToCopy);

console.log(copiedObject);

// outputs:
// { test: 12345, nested: { val: 6789 } }

Note the use of the first parameter with an empty object {} - this tells extend that the copied object(s) need to be copied to a new object. If you use an existing object as the first parameter, then the second (and all subsequent) parameters will be deep-merge-copied over the first parameter variable.

Using the example variables above, you can also do this:

var anotherMergeVar = { foo: "bar" };

extend(copiedObject, { anotherParam: 'value' }, anotherMergeVar);

console.log(copiedObject);

// outputs:
// { test: 12345, nested: { val: 6789 }, anotherParam: 'value', foo: 'bar' }

Very handy utility, especially where I'm used to extend in AngularJS and jQuery.

Hope this helps someone else; object reference overwrites are a misery, and this solves it every time!
Reply

#9
for array, one can use

var arr = [1,2,3];
var arr_2 = arr ;

print ( arr_2 );

**arr=arr.slice(0);**

print ( arr );

arr[1]=9999;

print ( arr_2 );
Reply

#10
You can use **lodash** as well. It has a [clone][1] and [cloneDeep][2] methods.


var _= require('lodash');

var objects = [{ 'a': 1 }, { 'b': 2 }];

var shallow = _.clone(objects);
console.log(shallow[0] === objects[0]);
// => true

var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);

[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through