Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy a variable's value into another

I have a variable which has a JSON object as its value. I directly assign this variable to some other variable so that they share the same value. This is how it works:

var a = $('#some_hidden_var').val(),     b = a; 

This works and both have the same value. I use a mousemove event handler to update b through out my app. On a button click, I want to revert b to the original value, meaning the value stored in a.

$('#revert').on('click', function(e){     b = a; }); 

After this if I use the same mousemove event handler, it updates both a and b, when earlier it was updating only b as expected.

I'm stumped over this issue! What is wrong here?

like image 520
Rutwick Gangurde Avatar asked Sep 16 '13 13:09

Rutwick Gangurde


People also ask

How do I copy a number in JavaScript?

var obj = { w: 123, x: { y: 456, z: 789 } }; If you do a shallow copy of that object, then the x property of your new object is the same x object from the original: var copy = $. extend( {}, obj ); copy.

Can you assign a variable to another variable?

After a value is assigned to a variable using the assignment operator, you can assign the value of that variable to another variable using the assignment operator. var myVar; myVar = 5; var myNum; myNum = myVar; The above declares a myVar variable with no value, then assigns it the value 5 .


Video Answer


1 Answers

It's important to understand what the = operator in JavaScript does and does not do.

The = operator does not make a copy of the data.

The = operator creates a new reference to the same data.

After you run your original code:

var a = $('#some_hidden_var').val(),     b = a; 

a and b are now two different names for the same object.

Any change you make to the contents of this object will be seen identically whether you reference it through the a variable or the b variable. They are the same object.

So, when you later try to "revert" b to the original a object with this code:

b = a; 

The code actually does nothing at all, because a and b are the exact same thing. The code is the same as if you'd written:

b = b; 

which obviously won't do anything.

Why does your new code work?

b = { key1: a.key1, key2: a.key2 }; 

Here you are creating a brand new object with the {...} object literal. This new object is not the same as your old object. So you are now setting b as a reference to this new object, which does what you want.

To handle any arbitrary object, you can use an object cloning function such as the one listed in Armand's answer, or since you're using jQuery just use the $.extend() function. This function will make either a shallow copy or a deep copy of an object. (Don't confuse this with the $().clone() method which is for copying DOM elements, not objects.)

For a shallow copy:

b = $.extend( {}, a ); 

Or a deep copy:

b = $.extend( true, {}, a ); 

What's the difference between a shallow copy and a deep copy? A shallow copy is similar to your code that creates a new object with an object literal. It creates a new top-level object containing references to the same properties as the original object.

If your object contains only primitive types like numbers and strings, a deep copy and shallow copy will do exactly the same thing. But if your object contains other objects or arrays nested inside it, then a shallow copy doesn't copy those nested objects, it merely creates references to them. So you could have the same problem with nested objects that you had with your top-level object. For example, given this object:

var obj = {     w: 123,     x: {         y: 456,         z: 789     } }; 

If you do a shallow copy of that object, then the x property of your new object is the same x object from the original:

var copy = $.extend( {}, obj ); copy.w = 321; copy.x.y = 654; 

Now your objects will look like this:

// copy looks as expected var copy = {     w: 321,     x: {         y: 654,         z: 789     } };  // But changing copy.x.y also changed obj.x.y! var obj = {     w: 123,  // changing copy.w didn't affect obj.w     x: {         y: 654,  // changing copy.x.y also changed obj.x.y         z: 789     } }; 

You can avoid this with a deep copy. The deep copy recurses into every nested object and array (and Date in Armand's code) to make copies of those objects in the same way it made a copy of the top-level object. So changing copy.x.y wouldn't affect obj.x.y.

Short answer: If in doubt, you probably want a deep copy.

like image 60
Michael Geary Avatar answered Sep 20 '22 22:09

Michael Geary