2

Can anyone explain why the obj returns {a:2} instead of {a:1} in this case?

var obj = {a:1};
var data = {b:obj};
data.b.a = 2;

console.log(obj); // {a:2}
artnikpro
  • 5,487
  • 4
  • 38
  • 40
  • 1
    You did change the property? – Bergi Jan 19 '13 at 18:55
  • See related question: http://stackoverflow.com/questions/728360/copying-an-object-in-javascript – CraigTeegarden Jan 19 '13 at 18:56
  • 1
    As in most languages, objects are references in JavaScript... (And this doesn't have anything to do with shallow copying, by the way.) – Ry- Jan 19 '13 at 18:56
  • 1
    @minitech If objects are references, names are people. References refer to objects, and objects contain more references, but they're quite separate. –  Jan 19 '13 at 18:57
  • Can you explain why you expect it to work differently? – Dagg Nabbit Jan 19 '13 at 19:00
  • @delnan: Oops, that was just a bad accidental word. (Too late to change it now.) Thanks though. – Ry- Jan 19 '13 at 19:03
  • @GGG because I created an object with another object inside. And then I edit "data" object but not "obj". I thought it will work like it does with variables – artnikpro Jan 19 '13 at 19:08
  • 1
    But you didn't create another object, you just created another reference to the same object. If you want to "clone" objects without copying properties, try using the prototype chain. – Dagg Nabbit Jan 19 '13 at 19:11
  • @GGG I need to make full independent copy of the object inside another object, to be able to change it with no conflicts. – artnikpro Jan 19 '13 at 19:17
  • @artnikpro try something like this: `function F(){}; F.prototype = obj; var clonedObj = new F();` – Dagg Nabbit Jan 19 '13 at 19:18
  • @GGG thank you! Seems like it works! – artnikpro Jan 19 '13 at 19:45
  • no problem, see also [Object.create](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create) – Dagg Nabbit Jan 19 '13 at 19:49
  • Possible duplicate of [How do I correctly clone a JavaScript object?](https://stackoverflow.com/questions/728360/how-do-i-correctly-clone-a-javascript-object) – Sebastian Scholle Feb 28 '18 at 12:18

3 Answers3

3

objects in javascript are by reference, so when you change one reference you changed them. The meaning of this is you just created a shallow copy, you need to do a deep clone.

Deep copy can be made with jQuery this way:

// Deep copy
var newObject = jQuery.extend(true, {}, obj);

Read this why I used jQuery: What is the most efficient way to deep clone an object in JavaScript?
(It's John Resig here on Stackoverflow...)

Community
  • 1
  • 1
gdoron
  • 147,333
  • 58
  • 291
  • 367
  • 1
    Thank you for your reply. Can you tell me please how can I copy the `obj` with no conflicts without jquery or other libraries plz? – artnikpro Jan 19 '13 at 18:57
  • @artnikpro, it can be done with this: `newObj = JSON.decode(JSON.encode(oldObj));`, about performance and other problems... read the linked answer. – gdoron Jan 19 '13 at 18:59
  • @artnikpro: Follow the link in the second comment to your question. – Felix Kling Jan 19 '13 at 19:07
  • Seems like it is not simple to do. I will try to figure it out. Thanks. – artnikpro Jan 19 '13 at 19:14
0

In this case you're not cloning objects but rather setting additional references to the same variable. data.obj.a and obj.a point to the exact same memory location. Line 3 sets this memory value to 2.

To do a deep clone, try this:

var data = JSON.parse(JSON.stringify(obj));
robrich
  • 13,017
  • 7
  • 36
  • 63
0

if using an NS derived browser like FF:

var data = { b: eval ( obj . toSource ( ) ) } ;

or

var data = { b: eval ( uneval ( obj ) ) } ;

if not:

Object . function . deepClone = function(){ 
/*
     highly non-trivial to accommodate objects like:
              animal=123; animal.beastly=432;                                        ie. object "overloading"
              monster = new ( function ( ) { this . this = this } ) ( )            ie. self-referential / recursive
      Note: JSON cannot do these  but  toSource () can handle recursive structures
      alert ( new ( function ( ) { this . this = this } ) ( )  . toSource ( )  );
                                                                                                                   ie.    #1={this:#1#}
      alert ( new ( function ( ) { this [ this ] = this } ) ( )  . toSource ( )  );
                                                                                                                   ie.     #1={'[object Object]':#1#}
      alert ( new ( function ( ) { this [ this . toSource ( )  ] = this } ) ( )  . toSource ( )  );
                                                                                                                   ie.     #1={'({})':#1#}
      alert (    (     #1 = { '({})' : #1# }      )   . toSource ( )  );
                                                                                                                   ie.     #1={'({})':#1#}
*/
 }

var data = { b: obj . deepClone ( )  } ;

There are many, many, many attempts posted in SO to do deepClone as well as
The structured clone algorithm - Web developer guide | MDN

hint: The Emperor has No Clothes

ekim
  • 1
  • 1