I have the following code (I am using the jQquery libary):
var obj = {};
var objstring = '{"one":"one","two":"two","three":"three"}'
// first console output
console.log(objstring);
var jsonobj = $.parseJSON(objstring);
// second console output
console.log(jsonobj);
obj.key = jsonobj;
obj.key.test = "why does this affect jsonobj? (even in the second console output)";
// third console output
console.log(jsonobj);
My Question: When I do obj.key = jsonobj and I change values in the new obj.key. Why do values in jsonobj then also change? And how would I avoid that? (I want a new "copy" of jsonobj).
I made this test case: /
I have the following code (I am using the jQquery libary):
var obj = {};
var objstring = '{"one":"one","two":"two","three":"three"}'
// first console output
console.log(objstring);
var jsonobj = $.parseJSON(objstring);
// second console output
console.log(jsonobj);
obj.key = jsonobj;
obj.key.test = "why does this affect jsonobj? (even in the second console output)";
// third console output
console.log(jsonobj);
My Question: When I do obj.key = jsonobj and I change values in the new obj.key. Why do values in jsonobj then also change? And how would I avoid that? (I want a new "copy" of jsonobj).
I made this test case: http://jsfiddle/WSgVz/
Share Improve this question edited Jul 6, 2011 at 19:25 Lightness Races in Orbit 386k77 gold badges666 silver badges1.1k bronze badges asked Jul 6, 2011 at 19:23 BjörnBjörn 13.2k12 gold badges55 silver badges70 bronze badges 1- 5 Excellently-formed question and testcase. It's incredibly sad that this is so rare nowadays. – Lightness Races in Orbit Commented Jul 6, 2011 at 19:26
5 Answers
Reset to default 5I want to address a small piece of what is going on here, since others have done so well addressing the larger issues of JavaScript object references:
// second console output
console.log(jsonobj);
obj.key = jsonobj;
obj.key.test = "why does this affect jsonobj? (even in the second console output)";
This is the result of a documented WebKit bug, that console.log
statements do not output the object at the time of calling console.log
, but instead some time later.
That is because the object is not copied. The obj.key
property will only contain a reference to the object, so when you assign something to obj.key.test
the effect is the same as assigning it to jsonobj.test
.
You can use the jQuery method extend to create a copy:
obj.key = $.extend({}, jsonobj);
This will copy the values into the newly created object ({}
).
Because when you do obj.key = jsonobj
, there isn't some new, copied object in obj.key
; it's just a reference to the jsonobj
that already exists. So changes to obj.key
will also change jsonobj
, because they're actually the same thing.
This is because there is no copying going on -- there is only one object, which is referenced by various variables and properties. When you do obj.key = jsonobj
, you are merely copying the reference to the same object.
All objects in JavaScript are copied by reference, meaning:
var x = {};
var y = x;
x.foo = 22; // y.foo also = 22 since y and x are the same object
If you want obj.key != jsonobj
, you need to clone the object. By creating a new object:
obj.key = $.parseJSON(objstring);
or using jQuery to clone the existing one:
obj.key = $.extend({}, jsonobj);