In JavaScript variables are declared with let
and const
. This has been the case since ECMAScript 6 (2015). Nowadays, you should only use these in your code.
But if you’ve been in the programming world for a while, or if you look at outdated tutorials (really not very updated) you will find the var
syntax.
So it’s time to stop ignoring the blue elephant in the room 🐘 and talk a little about the old var
syntax.
Moreover, frankly it’s an interesting topic (and even fun) if you want to see how sometimes things don’t go quite right, and how difficult it is to fix them.
Variable Declaration with var
The var
keyword is the original syntax for declaring variables in JavaScript since the first version, ECMAScript 1.
var age = 25;
console.log(age); // 25
In this example, age
is declared with var
and assigned the value 25
.
Before ES6, var
was the only way to declare variables in JavaScript. At first glance, it seems like a “pretty normal” syntax 🤷.
However, the behavior of var
variables had certain “peculiarities” that were not very intuitive for programmers.
In short, using variables with var
, instead of working like most languages, did it “its own way”.
Allow me to add a bit of humor to the matter 😊.
Characteristics of var
Let’s see what these “peculiarities” were 👇
First, variables defined with var
have function scope. This means that a variable declared with var
is accessible throughout the function in which it is declared.
function myFunction() {
if (true) {
var message = "Hello World";
}
console.log(message); // message is accessible here ⚠️
}
myFunction();
In this example,
- The variable
message
is accessible outside theif
block 😮 - This is because
var
has function scope, meaning it exists throughout theexample
function.
This is very different from most other languages, where the scope is generally at the block level (what’s between {}
).
Another of the peculiarities of var
is its behavior with hoisting. This means that variable declarations are elevated to the top of their scope, but initializations are not elevated.
As a result, variables declared with var
are accessible before their declaration, but their value will be undefined
until the line where they are initialized is reached.
// we access the variable before declaring it ⚠️
console.log(name); // undefined
var name = "Luis";
console.log(name); // "Luis"
In this example,
- The declaration of the variable
name
is hoisted to the beginning of the execution context - So we can use the variable before declaring it 😮
- It will give an
undefined
value in the first call toconsole.log
.
Finally, variables declared with var
could be redeclared within the same scope without any error occurring.
var number = 5;
var number = 10; // I redeclare it
console.log(number); // 10
Here, the second declaration of number
overwrites the first one 😮
The three things independently were quite bad. But together they were terrible (a truly dangerous and chaotic mess of variables) 🤦.
The New let
and const
The peculiarities of var
are understandable in the way it emerged JavaScript (resources of the machines of the time, ease of use, etc). Frankly, it was not expected to have such an impact as it does today.
However, as the language became more important, these peculiarities made development much more difficult, especially in medium and large projects.
So, in the great renormalization that ES6 represented, they took the opportunity to modify the way variables were handled (they became more similar to what is found in most other languages).
Thus, let
and const
arose (which we already know) and were precisely designed to fix these behaviors that var
had.
Feature | let/const | var |
---|---|---|
Scope | Block | Function |
Hoisting | No | Yes |
Multiple Declarations | No | Yes |
They have block scope, which means that a variable declared with let
or const
is only available within the block in which it is declared, such as in an if
or a for
.
function myFunction() {
if (true) {
let message = "Hello World";
}
console.log(message); // ❌ ReferenceError: message is not defined
}
myFunction();
They also have hoisting, but they are not initialized. Additionally, the concept of Temporal Dead Zone (TDZ) is introduced.
// we access the variable before declaring it
console.log(name); // ❌ ReferenceError: name is not defined
let name = "Luis";
console.log(name); // "Luis"
That is to say, if we try to access a variable declared with let
or const
before its declaration, it results in a ReferenceError
.
They do not allow redeclaring the same variable in the same scope. Attempting to do so results in a SyntaxError
.
let number = 5;
let number = 10; // ❌ SyntaxError: Identifier 'number' has already been declared
In Summary
For many, the behavior of var
was a mistake in the design of JavaScript, which we have inherited since its beginnings.
In fact, part of the “hate” that sometimes falls on JavaScript is due to things like the behavior of var
(and because they haven’t realized that things have changed).
We must also take into account the resources that the machines of the time (1995) had compared to what we have today, as well as the improvements in current interpreters.
Today, the variable declaration with var
is still functional. It cannot be removed for backward compatibility reasons with older code.
I like it as a story to illustrate how sometimes, some decisions are very hard to undo (because you have millions of lines of functioning code)
However, currently, the use of var
is totally discouraged. Instead, always use the syntax defined in ES6 with let
and const
.