The ultimate guide to variables in JavaScript

veronikasimic_56

Veronika Šimić

Posted on January 30, 2023

The ultimate guide to variables in JavaScript

potatoes

It was a day of potato harvest. Working on the field all day isn't easy and you are ready to go home to your family. You sit down, sigh deeply, and enjoy a bit of fresh air.

Suddenly the king's herald appears.

"Hear ye, hear ye! His Majesty the King hereby declares that a new tax on all peasants, merchants and traders within the kingdom shall be imposed. The revenue from this tax shall be used to fund the king's big appetite. All merchants and traders are required to pay this tax in full, and failure to do so shall result in severe penalties."

Quickly you collect all potatoes and make a run for it. No way you are giving the potatoes you stole, fair and square, to some king. You end up in the woods and hide behind a big bush thinking:

"It would be nice to store all of this potatoes somewhere safe."

And just like that you hear a voice:

Hey you, those are some nice looking potatoes. Would you like me to take care of them?

Var

"Who is that? Show yourself before I throw one of my potatoes on you."

My name is var. I have been storing various things for peasants and kings for 20 years. But now it seems that the whole world has forgotten about me.

"Hmm... I'm kind of tired from carrying these potatoes. It would be nice to rest. Ok, var store them."

var potatoes = 20;
Enter fullscreen mode Exit fullscreen mode

Thank you for this opportunity. Now if you want to retrieve them, just say the magic word console.log()

"Is there a way to protect them even more? It took me a long time to steal them."

How about this?

{
  var potatoes = 20;
}

console.log(potatoes);
Enter fullscreen mode Exit fullscreen mode

Output

20
Enter fullscreen mode Exit fullscreen mode

"So, no? You ain't block scoped? How am I going to protect them then?"

I may not be block scoped but I am function scoped.

function protectPotatoes() {
  var potatoes = 20;
}

console.log(potatoes);
Enter fullscreen mode Exit fullscreen mode

Now, no one can access them. Even our great queen and king could not get them.

Output

ReferenceError: potatoes is not defined
Enter fullscreen mode Exit fullscreen mode

In fact, I can even give them decoy potatoes and shadow your original potatoes.

var potatoes = 10;

function protectPotatoes() {
  var potatoes = 20;
}
console.log(potatoes);
Enter fullscreen mode Exit fullscreen mode

Output

10
Enter fullscreen mode Exit fullscreen mode

"Ha! Does this happen because potatoes are globally scoped when they are defined outside the function? And now when they are inside the function, that is they are function scoped, they are only available inside that function block?"

Well, for a peasant, you sure do know a lot of JavaScript. For that, I'm going to show you what else I can do with your potatoes.

console.log(potatoes);
var potatoes = 20;
Enter fullscreen mode Exit fullscreen mode

Output

undefined
Enter fullscreen mode Exit fullscreen mode

You see, even though we haven't met yet, I believed in you. I knew you were going to bring me some potatoes. The way I see it is this:

var potatoes;
console.log(potatoes);
var potatoes = 20;
Enter fullscreen mode Exit fullscreen mode

"Aha. So you are hoisted at the top? I can just declare that there are going to be some potatoes in the future. I don't need to assign anything yet? But there's just one thing I have been wondering. What if someone does this: "

var potatoes = 20;
var i = 1;

if (i > 0) {
  var potatoes = 0;
}

console.log(potatoes);
Enter fullscreen mode Exit fullscreen mode

Well, yes, now your potatoes aren't safe anymore. How are you only eating potatoes if you know so much JavaScript?

Output

0
Enter fullscreen mode Exit fullscreen mode

"I think this isn't a very good trait of yours. You are quirky and untrustworthy."

What did you just say to me? Say goodbye to your precious potatoes.

var potatoes = 20;
var potatoes = 0;
console.log(potatoes);
Enter fullscreen mode Exit fullscreen mode

Output

0
Enter fullscreen mode Exit fullscreen mode

"Noooooooo, my potatoes. No wonder no one likes you. You can even redeclare."

Tell you what, if you can guess what's going to happen now, I'm going to bring your potatoes back.

console.log(potatoes);

function getPotatoes() {
  var potatoes = 20;
  console.log(potatoes);
}

getPotatoes();
console.log(potatoes);
Enter fullscreen mode Exit fullscreen mode

"Well, I guess that I am having french fries for dinner! The correct answer is 20."

Ha. WRONG!!! What you get is nothing. You see, before the function is called, the first console.log(potatoes) is executed. But since there are no potatoes yet, we get an error. Also, what are french fries?

Output

ReferenceError: potatoes is not defined
Enter fullscreen mode Exit fullscreen mode

"Like I would tell you... thief!!"

Let 🌰

As you walk through the woods, defeated, hopeless and potatoless, you come across a tree of chestnuts.
After fighting a squirrel, you are faced with the same problem. A second voice appears:

Hail fellow, well met. Nice chestnuts you got there. What are you going to do with them?

"Who are you? var, is that you again? Get away from me!"

Oh easy there, my friend. I am not var. My name is let. I am var's cousin. I can store those chestnuts for you:

let chestnuts = 50;
Enter fullscreen mode Exit fullscreen mode

"var did the same thing before she stole my potatoes. Now I am forced to eat chestnuts for dinner. I don't know if you noticed but I am not a squirrel."

Really? And what about those two very long front teeth? It's unfortunate that you ran into var. But I can assure you that I am different.

"Oh, really? And why should I trust you?"

Because I can protect your chestnuts:

{
  let chestnuts = 50;
}

console.log(chestnuts);
Enter fullscreen mode Exit fullscreen mode

Output

ReferenceError: chestnuts is not defined
Enter fullscreen mode Exit fullscreen mode

"Now this is what I want. So you are block scoped, unlike that malicious var. What else can you do? Can you hide them inside a function?"

Well, yes that runs in our family.

function protectChestnuts() {
  let chestnuts = 50;
}

console.log(chestnuts);
Enter fullscreen mode Exit fullscreen mode

Output

ReferenceError: chestnuts is not defined
Enter fullscreen mode Exit fullscreen mode

"And what about decoy chestnuts? Can you do something like this?"

let chestnuts = 10;

function protectChestnuts() {
  let chestnuts = 50;
}
console.log(chestnuts);
Enter fullscreen mode Exit fullscreen mode

Yes, I've also inherited this from var.

Output

10
Enter fullscreen mode Exit fullscreen mode

"And what about this?"

console.log(chestnuts);
let chestnuts = 20;
Enter fullscreen mode Exit fullscreen mode

Well, no I can't do that. I have to be sure there are chestnuts before I can show them to you. I am not as gullible as var.

Output

ReferenceError: Cannot access 'chestnuts' before initialization
Enter fullscreen mode Exit fullscreen mode

"Aha. I guess you also don't have a problem with this:"

let chestnuts = 50;
let i = 1;

if (i > 0) {
  let chestnuts = 0;
}

console.log(chestnuts);
Enter fullscreen mode Exit fullscreen mode

Don't worry, even if someone has number 10, they won't be able to steal your chestnuts, I am block scoped, as you said.

Output

50
Enter fullscreen mode Exit fullscreen mode

"There's got to be something wrong with you."

Well, yes there is, but I don't like talking about it. Since your teeth remind me of Mary, I'll tell you anyway.

"Who's Marry? Your mother?"

No, she was my rabbit. Anyway, I can't do this:

let chestnuts = 50;
let chestnuts = 0;
console.log(chestnuts);
Enter fullscreen mode Exit fullscreen mode

Output

SyntaxError: Identifier 'chestnuts' has already been declared
Enter fullscreen mode Exit fullscreen mode

"Aha, so you can't steal them. Hey, look, another chestnut. Please store this one as well."

let chestnuts = 50;
chestnuts += 1;
console.log(chestnuts);
Enter fullscreen mode Exit fullscreen mode

Output

51
Enter fullscreen mode Exit fullscreen mode

Well, now that I look at them, I want them for myself. While I can't redeclare, I can reassign.

let chestnuts = 51;
chestnuts = 0;
console.log(chestnuts);
Enter fullscreen mode Exit fullscreen mode

Output

0
Enter fullscreen mode Exit fullscreen mode

"Noooooo, you give them back. I thought we were friends. Don't I remind you of your rabbit?"

We ate that rabbit. Bye now.

Const 🍄

So here you are again, all alone in the woods, your stomach growling, potatoless, chestnutless. You walk down to the creek and find a bunch of mushrooms. Quickly, you take as much as you can and think:

"Although I like stealing, I don't like it when someone does it to me. Is there anyone I can trust?"

You hear another voice, which makes you wonder where all of these voices are coming from?

Yo, what's good y'all! It's your boy const, the one and only true variable straight outta JS. I'm here to spit fire and drop some knowledge.

"Can you store this for me and not steal it?"

Ha, I guess you've met var and let. Not very nice, are they? But don't worry.

const mushrooms = 15;
Enter fullscreen mode Exit fullscreen mode

"And what if someone tries to do this?"

{
  const mushrooms = 15;
}

console.log(mushrooms);
Enter fullscreen mode Exit fullscreen mode

I got you, rabbit-man. Don't worry. Your mushrooms are safe.

Output

ReferenceError: mushrooms is not defined
Enter fullscreen mode Exit fullscreen mode

"I have been cheated more than once. What about this?"

function protectMushrooms() {
  const mushrooms = 15;
}

console.log(mushrooms);
Enter fullscreen mode Exit fullscreen mode

No way, I ain't like that. I am guarding your 'shrooms. We good.

Output

ReferenceError: mushrooms is not defined
Enter fullscreen mode Exit fullscreen mode

"So you are also block scoped. Can you do this: "

const mushrooms = 2;

function protectMushrooms() {
  const mushrooms = 15;
}
console.log(mushrooms);
Enter fullscreen mode Exit fullscreen mode

For sure. If you want them 'shrooms, tough luck.

Output

2
Enter fullscreen mode Exit fullscreen mode

"And you can't steal them? What about reassigning and redeclaring?"

const mushrooms = 15;
const mushrooms = 0;
console.log(mushrooms);

const mushrooms = 15;
mushrooms = 0;
console.log(mushrooms);
Enter fullscreen mode Exit fullscreen mode

Can't do that, ain't no way.

Output

SyntaxError: Identifier 'mushrooms' has already been declared
TypeError: Assignment to constant variable.
Enter fullscreen mode Exit fullscreen mode

"Finally, I have found a friend. Oh look, another mushroom. Please store this one as well."

const mushrooms = 15;
mushrooms +=1
console.log(mushrooms);
Enter fullscreen mode Exit fullscreen mode

I ain't with it, even for you, dawg, I'm out. I only keep values that don't change.

TypeError: Assignment to constant variable.
Enter fullscreen mode Exit fullscreen mode

"What? I am deeply offended. Now I am starting to miss var and let."

You didn't just say that. Oh, I am hurt. I bet let and var didn't show you that we can do this:

const mushrooms = {
  amount: 15,
};
mushrooms.amount = 0
console.log(mushrooms);
Enter fullscreen mode Exit fullscreen mode

Output

{ amount: 0 }
Enter fullscreen mode Exit fullscreen mode

"Nooooooooo. Not again. I thought you can't reassign values!"

Well, I can't except when it's objects. I kind of dig their vibe.

Wrap-Up

After a whole day's work, you go home potatoless, chestnutless, mushroomless.

Out of all the voices you've met, var is the most relaxed one, it's function scoped. Storing values inside var is not very safe since those values can be reassigned and redeclared.
Let is a little bit more rigid since it doesn't allow redeclaring but it does allow reassignment. It's block scoped just like const which is the strictest of them all. It doesn't allow redeclaring or reassigning, but it does have a soft spot for objects.

Very useful knowledge for a medieval peasant, don't you think? 🐰

💖 💪 🙅 🚩
veronikasimic_56
Veronika Šimić

Posted on January 30, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related