Logo Xingxin on Bug

JavaScript's var, let, const Confuse C++ Developer

January 9, 2025
4 min read

🔭At a Glance

Featurevarletconst
Scopefunction-scoped / globally-scopedblock-scopedblock-scoped
Mutabilitymutable (can reassign)mutable (can reassign)immutable (cannot reassign)
Hoistinghoisted, initialized to undefinedhoisted, not initializedhoisted, not initialized
Use Caselegacy code (avoid in modern JS/TS)changing valuesconstants

📜Golden Rule

Use const first → let when needed → var never (unless maintaining old code).

Intro

As a developer with a background in C/C++/C#, I’m familiar with the concept of variable declarations and scoping. However, JavaScript’s features left me confused😵. After reading a few articles, I decide to write down what I’ve learned.

Scope

Let’s start with scope. Scope refers to where the variable name is meaningful. Variables defined with let and const are both block-scoped, meaning they are only valid within the { }. In contrast, the var is function-scoped(defined inside a function) and global-scoped(defined outside a function).

So what?

OK. I know the var is not block-scoped. But why does it matter?

Look at the following code. What do you think the output will be?

var message = "Milk";
var decider = 13;
if (decider > 10) {
    var message = "Water";
}
 
console.log(message);  //OUTPUT: Water

Surprisingly, the output is “Water” but not “Milk”🤯! This is strange for a C++ developers as they are pretty sure the output should be “Milk” due to variable shadowing!

auto message = "Milk";
auto decider = 13;
 
if (decider > 10) {
    auto message = "Water";
}
 
std::printf(message);  //OUTPUT: Milk

Remark

This shows that var is not block-scoped. It leaks through { } blocks like water through a sieve.

Mutability

Remark

In this section, I would not address redeclaration as I prefer not to redeclare any variables.

When it comes to mutability, I always prefer const. However, there is a subtle detail about the const. See the following code

const PI = 3.14159;
PI = 3.14; //❌TypeError: Assignment to constant variable

and

const point = {x: 1, y: 1};
point.x = 2;   // ✅OK
point = {x:0, y:0}; //❌TypeError: Assignment to constant variable

Do you see a similarity to const in C++? From my perspective, this looks similar to the const pointer.

struct Person
{
    string name;
    int age;
};
 
//✅OK
Person* const p1 = new Person{.name = "John", .age = 21};
p1->name = "Jane";
 
//❌NO
p1 = new Person{.name = "John", .age = 21};

Hoisting

What you see is “hoisting” not “hosting”. Simply put, hoisting hides your mistake! When your code is like this:

console.log(writer);
var writer = "Shakespeare";

It actually works like so:

var writer;
console.log(writer);  //writer is undefined
writer = "Shakespeare";

The code will run, but the value will be incorrect! The benefit using const or let is that they will throw an error instead of hiding the problem.