6

I am currently dealing with understanding how values are assigned and passed around in Javascript. Primitive type's values are passed by value-copy, and object value types are passed by reference-copy.

If that is the case then why does this line of code not cause "yourAddress" variable to change the property of "street" to "321 cba street"?

var myAddress = {
  street: "123 abc st",
};
var yourAddress = myAddress;
myAddress = { street: "321 cba street" }; // doesn't change the val
myAddress.street = "321 cba street"; // doesn't change the val
console.log(yourAddress.street);

Why doesn't re-assigning the variable, or modifying the property name affect also the output of yourAddress.street since it has the same reference as myAddress.

Is the reason for this hoisting or am I not understanding something here internally with JS?

The version of this code that would work is this but why?

var myAddress = {
  street: "123 abc st",
};
myAddress = { street: "321 cba street" }; // doesn't change the val
myAddress.street = "321 cba street"; // doesn't change the val

var yourAddress = myAddress;

console.log(yourAddress.street);
  • edited my question, it was incoherent. – Abdul Nasir Jan 16 '20 at 15:36
  • 5
    re-assigning and modifying are two different things. If two variables have same reference and one of them is **modified(not re-assigned)** then the other will also change. – Maheer Ali Jan 16 '20 at 15:37
  • 8
    The second assignment to `myAddress` assigns a new, different object. After that, the two variables do **not** reference the same object. – Pointy Jan 16 '20 at 15:37
  • This could be related https://stackoverflow.com/questions/13104494/does-javascript-pass-by-reference – evolutionxbox Jan 16 '20 at 15:38
  • I see why is this allowed in JS? Isn't this a duplicate variable declaration? – Abdul Nasir Jan 16 '20 at 15:39
  • The variable is declared only once; when it is prefixed by the `var` keyword. You just reassign it. – Karl-André Gagnon Jan 16 '20 at 15:41
  • Thank you, I am understanding better, I guess undeclared and declared function is create a new reference somewhere in memory, so when I made another declaration with the same variable name myAddress, the yourAddress doesn't hold the same reference, myAddress is now stored as a new point in memory. – Abdul Nasir Jan 16 '20 at 15:48
  • @FZs yeah same question. – Abdul Nasir Jan 16 '20 at 15:50

2 Answers2

5
myAddress = { street: "321 cba street" }; // doesn't change the val

Yes, because this reassigns myAddress to point to a totally different object from yourAddress, so of course changes made thereafter to myAddress won't reflect to yourAddress. It's as if yourAddress = myAddress never happened.

Going back to the beginning of the program:

var myAddress = {
  street: "123 abc st",
};
var yourAddress = myAddress;

At this point, here's what the vars point to:

.------------------.
| object in memory | <------------ myAddress
`------------------`
         ^
         +------------------------ yourAddress

Then after the next line executes:

myAddress = { street: "321 cba street" }; // doesn't change the val

we have:

.------------------.
| object in memory | <------------ myAddress
`------------------`
.------------------.
| object in memory | <------------ yourAddress
`------------------`

These are two totally distinct objects being referenced by separate variables.

Remove the reassignment to myAddress and you'll see the change to the single object as accessed by multiple variables as you expect.

var myAddress = {street: "123 abc st"};
var yourAddress = myAddress;
myAddress.street = "321 cba street";
console.log(yourAddress.street, myAddress.street);

This situation (two references to one object in memory) is fundamentally the same as making a function call with an object parameter. A new variable is created on the function stack, but it's not a copy of the object; it's just a reference to the same underlying data.

var fn = param => {
  param.street = 42;
};

var myAddress = {street: "123 abc st"};
fn(myAddress);
console.log(myAddress.street);
ggorlen
  • 44,755
  • 7
  • 76
  • 106
1

As you already understand, non-primitive variables only hold a reference. This reference works just like any primitive type (only the reference, not the object): it can be copied, and reassigned without changing the other reference. So, in this code, foo.bar will still be 2:

let foo = {bar: 2};
let bar = foo;
bar = {bar: 5};
console.log(foo.bar);

The reference is copied just like any primitive type; the difference is that you can change an object through a reference.

CoderCharmander
  • 1,862
  • 10
  • 18