DEV Community

Cassidy Williams
Cassidy Williams

Posted on • Originally published at cassidoo.co on

Why JavaScript variables don't always update

I was helping a friend of mine with some technical interview questions, and a lot of them were very much like “what does this code output”-style questions (which I deeply dislike, I think these questions are more indicative of someone knowing really specific aspects of a language and less about software engineering, but I digress). One of them though I thought was interesting enough to write a technical explanation.

Values and objects

Look at this JavaScript code:

let [CLOSED, OPEN] = [{}, {}]

CLOSED = {
  cake: OPEN
}

OPEN = {
  fish: 5
}

console.log(CLOSED); // cake is {}
Enter fullscreen mode Exit fullscreen mode

Why is it that CLOSED is not { cake: { fish: 5 }}?

It’s because of how JavaScript assigns values and objects. In JavaScript, when you assign an object to another variable, you’re not creating a copy of that object. You’re creating a reference to that object.

So what’s happening here is that CLOSED and OPEN are both initialized as empty objects {}. When we assign CLOSED to { cake: OPEN }, it’s pointing at that empty OPEN object.

When you change OPEN to { fish: 5 } in this way, it assigns OPEN to a new object, and leaves the previously empty object behind. I say it like that because CLOSED still refers to the old empty object, and not the new one!

I say “in this way” because there’s another way to change OPEN: modify the existing empty object in place , so that CLOSED.cake references it even as it changes.

let [CLOSED, OPEN] = [{}, {}]

CLOSED = {
  cake: OPEN
}

OPEN.fish = 5;

console.log(CLOSED); // This now logs { cake: { fish: 5 }}
Enter fullscreen mode Exit fullscreen mode

Do you see how this is different? Instead of creating an entirely new object for OPEN to be reassigned to, we modify the properties of OPEN instead. CLOSED is still pointing to that object, and it’s just not a “left behind” object anymore!

I hope you don’t have to have this as an interview question, but you may run into similar problems as you build systems that use this as a concept.

User management example

Let’s say you have some kind of user management system. You might have an initial state of user accounts:

let state = {
  users: [
    { id: 1, name: "Cassidy", role: "admin" },
    { id: 2, name: "Yesenia", role: "user" },
    { id: 3, name: "Alan", role: "user" },
    { id: 4, name: "Gabor", role: "user" },
  ]
};
Enter fullscreen mode Exit fullscreen mode

If you wanted to promote a user to be an admin, you’d want to change the user object (by reference):

function promoteToAdmin(user) {
  user.role = "admin";
}
Enter fullscreen mode Exit fullscreen mode

(to reiterate: this changes the existing user object)

If you wanted to remove a user, you would want to change the state object (by value):

function removeUserById(userId) {
  state.users = state.users.filter(user => user.id !== userId);
}
Enter fullscreen mode Exit fullscreen mode

(this creates a new array with the filtered result)

So, if you want to promote Yesenia to admin:

let yesenia = state.users[1]; // Reference to Yesenia's object
promoteToAdmin(yesenia); // Directly changes her object

console.log(state.users);
Enter fullscreen mode Exit fullscreen mode

Try this in your console! You’ll see that the users array is all the same, except that Yesenia is an admin now.

If we wanted to remove Alan next:

removeUserById(3);

console.log(state.users);
Enter fullscreen mode Exit fullscreen mode

Again, this does not change the original users array, but returns a new array and assigns users to it.

If you run this yourself, note in your console that Yesenia is still an admin, showing that the update persisted!

Wow, I love JavaScript

Good for you. I have a love/hate relationship with it. But I mostly love it too, I guess. Kind of. I should value it more. Eh?? Ehhh????

Okay anyway, I hope this is helpful!

Top comments (2)

Collapse
 
alex_muriuki_3dd1dddd4779 profile image
Alex Muriuki

This was informative Cassidy, thank you!

Collapse
 
jcannon98188 profile image
jcannon98188

This by ref by val is true of literally every programming language. C forces it to be more explicit but this isn't really JS specific advice and is just general this is how programming works.