I’ve recently been using JavaScript a lot, while trying out Vue JS and Alpine JS in particular.
Something that often led to confusion was the result of assigning one variable to another. It sounds stupidly simple, but when it involves objects, it can lead to problems if it’s not done carefully.
After some research, during which I came across other people with misunderstandings, different interpretations and terminology, I know what’s going on.
Let’s start with a simple assignment of a string to a variable.
let Foo = "abc"
So JS creates a new value “abc” in memory. Then it creates a new variable “Foo”, and it connects the two. We can say that variable “Foo” is a pointer to the value “abc”.
Moving on, we’ll involve another variable.
Let Bar = Foo
Now JS creates variable “Bar”, but here’s the important bit … it doesn’t connect it with “Foo”. Instead, it makes “Bar” a pointer to the value “abc”. It’s a subtle difference, and in practice it doesn’t affect very much, but it’s important when we come on to considering objects rather than strings.
So now, in memory, we have one value “abc” and two variables “Foo” and “Bar”, both pointing to it.
On to the next step:
Foo = "xyz"
JS creates a new value “xyz” in memory, and changes “Foo” so that it points to this new value. Our other variable “Bar” is still pointing to “abc”, so it’s unaffected by this change to “Foo”. No surprises from a practical viewpoint – everything will work as expected. Let’s just finish off this section:
Bar = "efg"
This is familiar territory – JS creates a new value “efg” in memory, and changes “Bar” so that it points to this new value. The additional thing to note here, though, is that the value “abc” still exists in memory. But it has nothing pointing to it, and the JS garbage collector will be along at some point soon to get rid of it.
Now that’s clear, let’s move on to object assignment.
Let Foo = { name: "Joe", age: 32 }
Under the covers, this actually results in several values being created, but let’s keep it simple and say that this object now exists in memory with “Foo” pointing to it.
Let Bar = Foo
Just as with the string example earlier, we now have “Foo” and “Bar” both pointing to the same object value. Don’t misunderstand – “Bar” is not pointing to “Foo” as such.
Bar.name = "Amy"
Now, this is the bit that can cause problems for the unwary. We just changed the “name” property of the object value that is shared by “Foo” and “Bar”.
console.log (Foo.name)
This displays “Amy” in the console. So it looks like “Foo” has been changed as well as “Bar”. And for practical purposes, that’s the effect. But we know that it’s because they are both pointing to the same object value.
Just to prove the point, let’s reassign “Foo” and make it a string again.
Foo = "abc"
We already know what happens – a new value “abc” is created, and “Foo” is changed so that it points to it. But what about “Bar” – won’t that be affected? No – because “Bar” is still pointing to the object value with the name and age properties.
You regularly see mention of objects being assigned “by reference” and variables being somehow bound together. It’s not altogether true. Sure, variables can share values, but if we understand what goes on within JS, it helps us to maximise quality and develop better code.