Duplicate object in javascript

I see two ways to duplicate objects

one.

var a={c:1} var b=a; alert(bc);//alert 1 

2.

 var a={c:2}; var b={}; for (i in a) {b[i]=a[i];} alert(bc);//alert 1 

The former are shorter than the latter, so what is the efficiency in the second example?

+7
source share
4 answers

The first does not create a copy, but simply copies the link, so a and b point to the same object after the operation.

However, in the second case, each attribute is copied separately, thus creating a β€œreal” copy of the object in a (so far there are only primitive types in the properties, otherwise you will have the same problem with a deeper level).

So, in the first case, if you change bc , then ac will also change, and in the second case it will not.

+7
source

In the first version, you do not duplicate / clone an object, you simply add an additional link to it:

 var a = { a: 1 }; var b = a; ba = 2; console.log(aa); // 2; 

To clone an object, there are library numbers that can do this for you:

 var b = $.extend({}, a); // Make a shallow clone (jQuery) var b _.extend({}, a); // Make a shallow clone (underscore.js) var b = $.extend(true, {}, a); // Make a deep clone (jQuery); 

Or you can do it initially:
Simple clone:

 var b = {}; var prop; for (prop in a) { b[prop] = a[prop]; } 

Scratch deep cloning function:

 function deepClone(obj) { var r; var i = 0, var len = obj.length; // string, number, boolean if (typeof obj !== "object") { r = obj; } // Simple check for array else if ( len ) { r = []; for ( ; i < len; i++ ) { r.push( deepClone(obj[i]) ); } } // Simple check for date else if ( obj.getTime ) { r = new Date( +obj ); } // Simple check for DOM node else if ( obj.nodeName ) { r = obj; } // Object else { r = {}; for (i in obj) { r[i] = deepClone(obj[i]); } } return r; } 
+12
source

As other participants pointed out: the first assignment assigns a new link to an existing object, the second executes a shallow copy.
For small things, I mean: only the base object will be copied, there is no recursion

 var a = {some:'propery', another:{might:'be', an: 'object, too'} }; var b = {}; for(var p in a) { b[p] = a[p]; } b.some = 'b\ own property'; console.log(a.some);//property -> unaltered console.log(b.some);//b own property --> separate entities b.another.might = 'foo'; console.log(a.another.might);//foo ==> b.another references a.another 

To solve this problem, you will be forgiven to think that a simple recursive function is enough:

 var cloneObj = function(o) { var p,r = {}; for (p in o) {//omitting checks for functions, date objects and the like r[p] = (o[p] instanceof Object ? cloneObj(o[p]) : o[p]); } }; 

But tire of circular links!

 //assume a is the same object as above a._myself = a;//<- a references itself 

This will result in infinite recursion, such as a deadlock scenario, unless you add validation only for such cases:

 var cloneObj = function(o) { var p,r = {}; for (p in o) {//Needs a lot more work, just a basic example of a recursive copy function switch(true) { case o[p] instanceof Function: r[p] = o[p]; break; case o[p] instanceof Date: r[p] = new Date(o[p]); break; case o === o[p]: //simple circular references only //a.some.child.object.references = a; will still cause trouble r[p] = r; break; case o[p] instanceof Array: r[p] = o[p].slice(0);//copy arrays break; default: r[p] = o[p] instanceof Object ? cloneObj(o[p]) : o[p]; } } return r; }; 

Now this is pretty verbose, and in most cases, exhaustive search, if all you need is two objects with the same data, but they can be changed independently (i.e. do not refer to the same object in memory), everything, what you need 1 line of code:

 var a = {some:'propery', another:{might:'be', an: 'object, too'} }; var b = JSON.parse(JSON.stringify(a)); 

Bottom line: link assignment is certainly more efficient: it does not require the constructor of the object to be called a second time, nor does it require an additional copy of any of the constants.
Disadvantage: you fall into one object and can inadvertently change / delete what you think still exists when you use another link ( delete b.some;/*some time later*/a.some.replace(/p/g,'q');//<--error )

+4
source

The first copy of the link does not duplicate the object , the second creates a new link and then copies the elements (which, in turn, if they are links, just copy only the links).

You might want to look at this different SO - Does Javascript describe the sign of reference objects or clone them?

It is not a question of efficiency, ultimately, of correctness. If you need to share an object link between different blocks of code (for example, so that multiple pieces of code can share the same object), then you just rely on javascript to follow the link.

If, however, you need to copy an object between methods, then you can use your simple example in the second block of code (if your objects do not have other β€œobjects” in them), otherwise you may have to perform a deep clone (see How to clown in javascript and pay attention to the answer (there) is not a trivial business).

+3
source

All Articles