Language: EN

javascript-variables-var

The Old var

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”.

javascript-var

They said let’s do it grachioooocho

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 the if block 😮
  • This is because var has function scope, meaning it exists throughout the example 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 to console.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.

Featurelet/constvar
ScopeBlockFunction
HoistingNoYes
Multiple DeclarationsNoYes

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.