Reputation: 51947
I have an array of 20 objects BaseObjects called ArrayBaseObjects. The user calls an object, it's loaded in the UI, and he makes changes to the properties. Something like this:
var ArrayBaseObjects = new Array();
var CurrentObject = null;
function OpenRecord (TheIndex) {
CurrentObject = ArrayBaseObjects[TheIndex];
}
function RecordChanges() {
// bunch of statements that make changes to CurrenObject
CurrentObject.CrazyStuff = NewValue;
}
The problem is that when the user makes changes to the CurrentObject, it also changes the value of the ORIGINAL object in ArrayBaseObjects.
I don't understand why?? When I write CurrentObject = ArrayBaseObjects[TheIndex];
why does changing CurrentObject also affect the value of the objects in ArrayBaseObject??
I'm looking to compare that value between the orignal object and CurrentObject the user made changes to, but they're always the same! What changes do I need to make to get this to work the way I intend it?
Thanks for the explanation.
Upvotes: 1
Views: 63
Reputation: 59387
Pretty much everything in JavaScript is passed around by reference. That means unless you explicitly clone an object, assigning the object to a new variable means that now you have two variables pointing to the same object, and changes made to that object through one variable will be visible from the second.
For an answer on how to fix this, what you want is to clone
the object. However, this isn't necessarily a trivial thing to perform in an elegant way.
Fortunately, JavaScript ninjas out there have already done the hard work. I would suggest using jQuery and it's excellent extend()
method, which you can specify to do a deep copy. This makes sure that all the data in the object gets cloned, rather than just the top level references.
For more information see this question.
In your case, you would use it like so:
var ArrayBaseObjects = [];
var CurrentObject = {};
function OpenRecord (TheIndex) {
// This will perform a deep copy of all elements of the ArrayBaseObjects[TheIndex]
// into CurrentObject
jQuery.extend(true, CurrentObject, ArrayBaseObjects[TheIndex]);
// You could also call it like this, if you didn't need the CurrentObject variable:
// var clonedObject = jQuery.extend(true, {}, ArrayBaseObjects[TheIndex]);
}
function RecordChanges() {
// bunch of statements that make changes to CurrenObject
CurrentObject.CrazyStuff = NewValue;
}
Upvotes: 2
Reputation: 1330
that is because assigning ArrayBaseObjects[TheIndex] to CurrentObject is assigning a reference. See here for how to "clone" an object:
What is the most efficient way to deep clone an object in JavaScript?
Upvotes: 0
Reputation: 88378
The reason is that variables hold references to objects and not the objects themselves.
The statement
CurrentObject = ArrayBaseObjects[TheIndex];
makes the value of CurrentObject
be the same as the value of ArrayBaseObjects[TheIndex]
. Both values are references, or pointers, to the same object. There is only one object here although there are two variables. You can change properties of this single object through either variable, and you will "see this change" through the other variable.
It all comes down to understanding the difference between variables and objects. It is very common in JavaScript to refer to one object with multiple variables. This happens whenever you assign an object to a variable, or pass an object as an argument to a function.
Here is a simple test:
var a = {x:1, y:2};
var b = a;
b.x = 5;
alert(a.x); // 5
Why?
+---------+
a ----------> | x [ 5 ] |
| y [ 2 ] |
+---------+
^
|
b -----------------+
One object, two variables.
Upvotes: 1