6

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.net/WSgVz/

1
  • 5
    Excellently-formed question and testcase. It's incredibly sad that this is so rare nowadays. Commented Jul 6, 2011 at 19:26

5 Answers 5

5

I 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.

Sign up to request clarification or add additional context in comments.

3 Comments

I tried to make it much clearer what I was getting at this time around, so please explain any -1 votes...
oh ok, this only contributed to my former false understanding of how javascript handles object copying/delegation. thank you for pointing this out ;).
Changed my -1 to a +1. At the time of my vote you didn't have as detailed of an answer. Now I have egg on my face.
3

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 ({}).

2 Comments

Also worth noting you'll need $.extend(true, {}, jsonobj) for deep copy (as opposed to shallow one-level copy).
@Domenic: Good point, that's good to know for more complex object structures.
2

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.

Comments

1

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.

Comments

1

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);

2 Comments

But I don't seem to find the answer behind the output of the second log..........
the 2nd log statement is just wrong, per Domenic's answer. If you want a valid console.log: console.log(JSON.stringify(jsonobj))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.