Pass by value of reference... (JS woes)

Pass an object to a function and change it inside the function. Hey, surprise, it’s changed at the call site, too. Okay, so we’re passing by reference. Now, do the same, but assign something else to it. This does not change the object at the call site. What the…?!

Did a little research, found out that they call this “pass by value of reference”. Now, I kind of understand the logic behind it, but… Hey, either be consistent or allow me to control how I want to pass things myself.

Oh well, make an explicit copy then. But hey, did you know that there’s no built-in way to create a deep copy of an array?

Am I being a stupid tourist or is JS just weird?

This is actually the norm in Python too, and a lot of languages. Even in C if you pass simple types you can’t change them without using a pointer.

I think the reason is it’s easier to reason about what’s happening in a piece of code if the function doesn’t change things without warning. When you pass in a variable as a parameter it’s expected that the function won’t break it, so unless the parameter is named with blah_out you don’t really know that it’s going to be modified and that can ruin your day.

The norm in JavaScript then seem to do either:

  1. Return the newly updated elements with a new object (which can be exploded).
  2. Accept an object, and modify it, but document this.

So you can write a function like this:

const myfunc = (a, b, c) => {
   // do stuff with a, b, c to make x, y, z
   return [x, y, z];
}

let [hair, eyes, blood] = myfunc('Brown', 'Blue', 'Red');

That will explode out the returned list and make those three variables. The object syntax also works:

const myfunc = (a, b, c) => {
   // do stuff with a, b, c to make x, y, z
   return {x, y, z};
}

let {hair, eyes, blood} = myfunc('Brown', 'Blue', 'Red');

The difference is that if you return an object then your variables must be named the same as the keys in the object. If you return a list then the assigned variables can be anything.

1 Like

Oh wow, it’s actually the same in Python. What tripped me up is the fact that you can have side effects inside objects, but reassignment does not propagate outside the function. I’ve done a lot of C++ lately and there it’s all kind of more logical. It’s also usually very clear whether something will be changed because you’ll only take a const reference as a parameter if not.

Anyway, thanks for the detailed explanation!

A free service run by Zed A. Shaw for learncodethehardway.org.