Back to the roots - A var, let and const story
vladutcoman
Posted on October 19, 2021
An endless story, yeah? Oke, let's start with some introduction
If you ask someone why sometimes JS is so confusing, probably one of the reasons is varπ© declaration.
That was my experience too in 2017 when I had my first contact with JS. It was post-ES6(ES2015), which means the let and const were there.
I thought: "lucky me, var is history and now we live in a new era" π. Guess what happened? Yeah, I was hit by a var bug in the face. TKO ππ΅, not stand a chance.
It's true that with ES2015 we have great alternatives for declarations in letπ₯ and constπ₯, but it is also important to know how var works (and pray we do not go into it π ).
Now, why are let and const such a great option? Well, let's see! π
Scope
π Let's try to understand it first: in a few words, scope represents where these variables are available for use.
- var
Variables defined with var have global or function scope.
Global scope -> when they are defined outside any function and are available in the whole window
Function scope -> when they are defined inside a function and are available inside that function
var globalScope = 'global';
function varFcn() {
var functionScope = 'function';
console.log(globalScope); // -> 'global'
console.log(functionScope); // -> 'function'
}
console.log(globalScope); // -> 'global'
console.log(functionScope); // -> Uncaught ReferenceError: functionScope is not defined
- let
Let declarations have block scope. What is a block? Well, a block is a code between {} - anything between curly braces is a block.
Here is a comparison example to better understand the difference:
var foodWithVar = 'salad';
if (true) {
var drinkWithVar = 'beer';
}
console.log(foodWithVar); // -> 'salad'
console.log(drinkWithVar); // -> 'beer'
// Versus let declaration
let food = 'salad';
if (true) {
let drink = 'beer';
}
console.log(food); // -> 'salad'
console.log(drink); // -> 'Uncaught ReferenceError: Can't find variable: drink'
- const
Is the same as variables declared with let.
Hoisting
π Hoisting is a Javascript voodooπ§ where variables and functions declarations are moved to the top of their scope before the execution.
- var
Besides being hoisted, the var variables are also initialized with undefined.
console.log(food); // -> undefined
var food = 'pizza';
console.log(food); // -> 'pizza'
// The code above is interpreted like this:
var food; // default value for var declaration is 'undefined'
console.log(food); // -> undefined
food = 'pizza';
console.log(food); // -> 'pizza'
- let
Declarations with let are also hoisted, but unlike a var, they are not initialized with undefined.
console.log(food); // -> Uncaught ReferenceError: Cannot access 'food' before initialisation"
let food = 'pizza';
console.log(food); // -> 'pizza'
// The code above is interpreted like this:
let food; // let declaration has no default value
console.log(food); // -> Uncaught ReferenceError: Cannot access 'food' before initialisation"
let food = 'pizza';
console.log(food); // -> 'pizza'
- const
Is the same as variables declared with let.
Redeclaration and reassignment
- var
β I will say just this: var variables can be redeclared! π
var food = 'pizza';
var food = 'salad';
console.log(food); // -> 'salad'
// This is madness! Who wants salad instead of pizza...?
Also, vars can be reassigned.
π One thing I found out from a colleague is that in the pre-ES6 era, var redeclaration was used as a safety measure for controlling the value of the variable. Or to make sure the value is "clean". Seems like a nice hack, but also... strange, right?
- let
Let variables can not be redeclared, but can be reassigned. π₯³
// Redeclaration not working
let food = 'salad';
let food = 'steak'; // SyntaxError: Identifier 'food' has already been declared
// Reassignment is working
let drink = 'tea';
drink = 'beer';
- const
Const variables can not be redeclared nor reassigned.
const drink = 'tea';
drink = 'beer'; //TypeError: Assignment to constant variable.
const food = 'salad';
const food = 'steak'; // SyntaxError: Identifier 'food' has already been declared
But here is something interesting: π if you have an object declared with const you can modify his properties.
const meal = {
food: 'pizza',
drink: 'cola'
};
meal.drink = 'pepsi';
meal.dessert = 'cake';
console.log(meal);
/*
{
dessert: "cake",
drink: "pepsi",
food: "pizza"
}
*/
const meals = ['lunch'];
meals.push('dinner');
console.log(meals);
/*
["lunch", "dinner"]
*/
Sort of conclusion
Look, I am not saying you should or should not use var. But, you need to be extra careful when using var because the math is not lying:
function scope + hoisting + redeclaration === π€―
Don't believe me? Check this simple example:
var food = 'salad';
if (true) {
var food = 'burger';
}
console.log(food); // -> 'burger'
π¨ So, food was re-declared and modified. That is a real problem (besides having burgers all the time not being very healthy). If you have used food in other parts of the code, you could be surprised by the output you might get. That can cause a lot of bugs in the code.
That is just one of many examples of how wrong things can go when using var without knowing how it works. π
Also, var is common in legacy code. And if you don't know how let and const works, maybe it's easy to go with var. But, for me, let and const are the way to go and I encourage you to give them a try.
Well, I guess that's it for now. May the let-const be with you! Cheers π»
Posted on October 19, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.