DEV Community

Hal Friday
Hal Friday

Posted on

JavaScript Stuff I Thought Was Weird Which Just Turned Out to Make Sense After All

When I first started learning JavaScript, I definitely had a beat-it-to-fit, paint-it-to-match mentality. My wrangling of code was basically just elbow grease and duct tape, and I filed a lot of things away as cute little mysteries, assuming that JavaScript kept as them a personality quirk.

keep your secrets

But it turns out, most of the stuff that I thought was totally bonkers, actually does make sense when you get down to the brass tacks of it.

I'm writing this post about a favorite example of this. Here are two code snippets which are true:

let uno = 1

function topple (arg){
    arg += 1 
}

topple(uno)

console.log(uno)
    => 1
Enter fullscreen mode Exit fullscreen mode

and

let arr = []

function topple (arg){
    arg[0] = "toodledoo"
}

topple(arr)

console.log(arr)
    => ["toodledoo"]
Enter fullscreen mode Exit fullscreen mode

As a newbie programmer, this made absolutely no sense. In one case, you pass an argument and perform an alteration, and it does not change the variable. In the second case, it totally does change the variable. I'm also a bootcamp grad, so at the time I really had to pick my battles for which topic I could do a deep dive into, and this was not one of them. I settled for memorizing the truth that you could change arrays and hashes, but for some reason you couldn't get the same functionality out of variables pointing to a string or a number. I'm...perhaps a little too good at going with the flow, so for a while I chalked it up to a silly weird thing left it at that.

Since I've had a little more time and a lot more freedom to explore topics of interest, I've found some super fascinating things out about that code.

Firstly, I learned that in JavaScript, there are a limited number of types that any one piece of code can be. Here are all of them:

  1. String
  2. Number
  3. Boolean
  4. Object
  5. Function
  6. Undefined
  7. Null
  8. Symbol
  9. Bigint

And that's it. Everything you touch and see and get slapped with in the form of an error message is gonna be one of these things. For the purposes of explaining the weirdness above, I'm really just going to talk about Numbers and Objects.

Before moving on, it's paramount to define Objects, because I feel like that gets thrown around a lot with different meanings. In terms of the underlying skeleton of JavaScript, MDN Docs defines an Object like this:

In computer science, an object is a value in memory which is possibly referenced by an identifier.

Which, is just, so useless. What does that even mean? You may have heard elsewhere that "everything in JavaScript is an object," and I feel like that's closer. That's almost true. Arrays, hashes, regex, these are all objects. Importantly, Objects are mutable. Changeable. Hashes and arrays can alter their contents constantly.

There are a few things in JS that are not objects, and numbers are one of them.

Numbers are considered a special sort of thing in JS, called a "primitive." Primitives are immutable. Can you change the value of one? Think for a sec, what if you add 1+5...Does 1 stop being 1? Nope, 1 will always exist, in its primitive state, unchanging.

So, that brings us back around to our examples. Let's take a deeper look into the first example.

let uno = 1

function topple (arg){
    arg += 1 
}

topple(uno)

console.log(uno)
    => 1
Enter fullscreen mode Exit fullscreen mode

Step One: Set a variable called uno which points to the primitive number 1.

Step Two: Define a function which accepts an argument, and in the body of the function, permanently increases that argument by 1.

Step Three: Call function. Hand it our uno variable. This step is where the secret magic happens that I previously didn't understand. I was saying things like "hand it a variable" but failing to realize that you can't hand anything a variable in JavaScript. You hear that craziness? You go around for a couple years of your life thinking that you pass information in your code around using variables and it's a total lie. You can't hand anything a variable in JavaScript.

It's because variables are instantaneously evaluated. In step three, we aren't handing that function anything called uno, we are handing it a tiny puzzle, which JavaScript works out right then and there in the arguments. It follows uno back to the source and finds out that we set it to point to the number 1, and it actually just passes the number 1 through to the body of the function. The reason that our variable is unchanged on the other side of the function is that our body never saw nor touched the variable.

Okay. Now, that is super cool, and very exciting to be able to see the secrets of JavaScript happening in real time -- I imagine this is how I would feel if I could watch human bones and tendons interacting with perfect clarity under the skin of a living person. I wonder if surgeons get this feeling.

But we still have another mystery on our hands: If this first example can't alter the variable, why in God's green earth would it be able to alter the second one, in a nearly identical example?

Remember what we talked about with the mutable items versus the non-mutable items. As we said before, there is only one 1. You can't change the number 1, and any time you reference it, you are always pointing at the same ol' number 1. One symptom of being mutable is the ability to be multiple. Because arrays can change, they can have many different instances that exist in different places in your computer's memory. You can get a really good visual of this by running a short test in your browser's console. First, run this code:

for(let i=0;i<10;i++){
     console.log(1)
}
Enter fullscreen mode Exit fullscreen mode

Notice the result. Now don't clear your screen, and run this code:

for(let i=0;i<10;i++){
     console.log([])
}
Enter fullscreen mode Exit fullscreen mode

With the first one, you see the number 1 with a little 10 to the left of it, indicating that the number was logged 10 times in a row. What's up with the next one? Why does it show ten arrays logged on separate lines?

Right, it's not repeating anything. Those are all different arrays.

Cool, so it's possible that you've already put together where I'm going with this, but might as well finish it out. Let's dive into the second example like we did the first.

let arr = []

function topple (arg){
    arg[0] = "toodledoo"
}

topple(arr)

console.log(arr)
    => ["toodledoo"]
Enter fullscreen mode Exit fullscreen mode

Step One: Set a variable called arr which points to some new object.

Step Two: Define a function which accepts an array, and in the body of the function, permanently adds "toodledoo" to that array.

Step Three: Call function. Hand it our arr variable.

But! As we know, you can't pass variables anywhere in JS. So arr will get evaluated right then and there, and JavaScript will instead pass the array itself into the body of the function. And here's where it all comes together:

Because you can have multiple arrays in a single coding project, and because each individual array holds a different place in memory, when our function adds "toodledoo" into the array that it's given, that changes its value in the actual computer. So when we go to check the variable again, it doesn't try to grab a new array, it goes back to the place in memory where our array was stored and finds that this particular instance has been changed.

To recap: If you pass a function the number 1, it can't change that number at all. Even if you set 10,000 variables to the number 1, they'd all be pointing to the same place in memory, cause nobody can mess with math. However, if you pass a function an object such as an array, all new objects point to a different place in memory, so if you change that array you can still see the changes later down the line.

Fascinating, like I said. Now, one last thing. This code is also true:

let uno = 1

function topple (){
    uno += 1 
}

topple()

console.log(uno)
    => 2
Enter fullscreen mode Exit fullscreen mode

Why do you think that is?



All credit to Dan Abramov and his wonderful newsletter for helping me become a more enlightened programmer.

Top comments (0)