What’s wrong with using ‘var’ in JavaScript?
Last updated: September 5, 2022.
Before the ES6 upgrade to JavaScript (2015) there was only one way to declare a new variable: using the var
keyword.
The upgrade introduced two new keyword for declaring variables: let
and const
.
Since then, the use of var
has generally become seen as something of a bad practice.
So, what exactly is wrong with using var
?
Table of contents
Reasons not to use ‘var’
#1: ‘var
‘ lacks block scope
Generally, you don’t want a variable created in a larger construct to be accessible outside it. When this occurs, it is known as ‘leakage’.
While this can sometimes be intentional, it can also occur accidently, leading to unwanted outcomes.
A feature of var
is that is lacks block scope. This means that it is not contained within a loop
or if...else
statement.
Take the following example:
for (var i=0; i<=3; i++) {
console.log(i); // 0 1 2 3
}
console.log(i); // 4
What you would probably want here is for i
to exist only within the loop. But, because it has been declared with var, it 'leaks' out of its block scope and is available afterwards in the global scope.
Declare the variable with let
and there is no leakage:
for (let i=0; i<=3; i++) {
console.log(i); // 0 1 2 3
}
console.log(i); // Uncaught ReferenceError: i is not defined
#2: 'var
' is hoisted
Try to do something with a non-existent variable and it, predictably, result in an error:
console.log(x); // Uncaught ReferenceError: x is not defined
But declare a variable afterwards using var
and this changes:
console.log(x); // undefined
var x; // <-- Declaration is hoisted
x = 3; // <-- Value not hoisted
This is because the declaration of a variable with var
is 'hoisted': at runtime, it is processed before anything else in its scope is executed. This is why you can make reference to it before it is created.
Note that the value is not hoisted. This is because variable initialization (assignment of a value to the variable) is not hoisted.
In other words, the code above is read as follows by the interpreter:
var x;
console.log(x);
x = 3;
This example is in the global scope but the same behavior also occurs inside of functions since var
does have function scope.
With let
and const
, hoisting does not occur: you cannot access a variable before it is declared in your script:
console.log(x); // Uncaught ReferenceError: Cannot access 'x' before initialization
let x;
x = 3;
#3: A variable can be redeclared using 'var
'
You usually don't want to create a variable under the same name as one you've already created because you then (perhaps unwantedly) lose the original value.
Instead, you'd want an error to be thrown so you can declare the variable under a different name.
But with var
, no error is thrown. Instead, the original variable is silently overwritten:
var OG = "Al Capone";
console.log(OG); // Al Capone
var OG = "Baby Face";
console.log(OG); // Baby Face
Al Capone will not be happy.
Using let
, you cannot use the same variable name twice:
let OG = "Al Capone";
console.log(OG); // Al Capone
let OG = "Baby Face"; // Uncaught SyntaxError: Identifier 'OG' has already been declared
console.log(OG);
Take that, Baby Face!
#4: 'var
' creates properties on the window
object
When using var
in the global scope, you are creating new properties on the window
object.
This is usually harmless, but can lead to unexpected outcomes.
For example, if you create a variable with the name of a method existing on the window
object, it will silently overwrite it.
For example:
var fetch = "Bro";
console.log(window.fetch);
Uh oh, bro. You just overwrote the amazing fetch()
function with the much less useful property value of "Bro"
.
Avoid these issues: use 'let
' and 'const
'
Though var
is not 'broken' and its flexibility can make it more beginner-friendly, in practice it can lead to unexpected outcomes.
These potential pitfalls can be avoided by using let
and const
.
The differences between these two are:
- Value must be assigned upon variable declaration?
const
: yes ✔️let
: no ❌
- Variable value can be reassigned later:
const
: no ❌let
: yes ✔️
In other words, const
is a stricter version of let
, intended for initializing a variable with a value that shouldn't be overwritten.
But both avoid the problems associated with var
outlined above.