Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
146 views
in Technique[技术] by (71.8m points)

javascript - 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?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...