Setting a variable equal to another variable [duplicate]
I have a few questions about setting a variable equal to another variable in JavaScript.
Let's say we create an object, a
and set b = a
.
var a = {
fname: "Jon",
lname: "Smith",
age: 50
}
var b = a;
I understand that if we change one of a
's properties b
will also be changed because when we set b = a
we don't clone a
's data, but rather create a reference to a
's data. For example if we set a.fname = "Sarah"
, the new value of b.fname
will be "Sarah"
.
If we try to "clear" a
though by setting a = {}
, object b
will remain unchanged. I don't understand why manipulating an object in this way produces a different result than in the 1st example.
Also I have a question about the following scenario.
var x = 10;
var z = x;
If we then set x = 20
, the value of z
remains unchanged. Based on the behavior described in my 1st question, one would think that the new value of z
would reflect the new value of x
. Could someone please explain what I am missing here?
Thank You!
The really short answer to both your questions is that when you make one variable equal to another, a COPY of what's in the first variable is made and stored in the second variable - there is no linkage between the two variables.
But, read on for more details and why it can seem like there is a link in some cases...
JavaScript, like many languages, divides data into two broad categories: value types and reference types. JavaScript value types are its primitives:
- string
- number
- boolean
- null
- undefined
- symbol
When you assign any of these types to a variable, the actual data is stored in that variable and if you set one variable equal to another, a copy (not a linkage) of the primitive is made and stored in the new variable:
var a = 10; // Store the actual number 10 in the a variable
var b = a; // Store a COPY of the actual number stored in a (10) in the b variable
a = 50; // Change the actual data stored in a to 50 (no change to b here)
console.log(b); // 10
When you work with reference types, something a little different happens. Assigning a variable to a reference type means that the variable only holds a reference to the memory location where the object is actually stored, not the actual object itself. So, when you do this:
var a = {foo:"bar"};
a
does not actually store the object itself, it only stores the memory location for where the object can be found (i.e. 0x3C41A).
But, as far as setting another variable equal to the first goes, it still works as it did with primitives - - a copy of what's in the first variable is made and given to the second variable.
Here's an example:
// An object is instantiated in memory and a is given the address of it (for example 0x3C41A)
var a = {};
// The contents of a (the memory location of an object) is COPIED into b.
// Now, both a and b hold the same memory location of the object (0x3C41A)
var b = a;
// Regardless of whether a or b is used, the same underlying object
// will be affected:
a.foo = "test";
console.log(b.foo); // "test"
// If one of the variables takes on a new value, it won't change
// what the other variable holds:
a = "something else";
console.log(b); // The object stored in memory location (0x3C41A)
So, in your first tests, you've simply got two ways of accessing one object and then you change what a
is holding (the memory location of the object) to a different object and therefore now you only have one way left to access the original object, through b
.
If we try to "clear"
a
through by settinga = {}
, objectb
will remain unchanged. I don't understand why manipulating an object in this way produces a different result than in the 1st example.
Because now we know that a = {}
isn't clearing the object. It's just pointing a
at something else.
Let me try to explain:
1) In your example a
and b
are references to one and the same object, while a.fname
(or b.fname
) is an attribute of that object. So when manipulating the attribute it will be changed in the object, while the references won't be affected, they still point to the same object, the object itself has been changed. a = {}
on the other hand will just replace the reference to the object without affecting the object itself or b
's reference to It.
It's no clearance btw you only just created a new reference to a new empty object.
2) These are not objects, so there is no reference you are directly manipulating the values. That' s because there's a difference between objects and primitives which might get confusing especially in the beginning if you're not used to working with strict types.
In your first case:
var a = {
fname: "Jon",
lname: "Smith",
age: 50
}
var b = a;
a = {}
b
remains unchanged because this is the sequence of events happening in the background:
-
You create an object at memory address 0x1234 with the data
fname: "Jon",
lname: "Smith",
age: 50
A pointer to that memory block is stored in
a
.- Then that pointer is copied to
b
At this point there are two references to the same bit of memory. Altering anything in that memory block will affect both the references to it.
-
a = {}
doesn't clear out memory block 0x1234, but creates a new object on another memory location (0x1235) and stores a pointer to that block ina
. The memory at 0x1234 remains unchanged becauseb
is still pointing to it.
There is a difference in this sort of memory management between simple variables and objects/pointers. Strings and numbers are of the simple variety and are 'passed by value' as opposed to being 'passed by reference' for objects.