In ES2015(ES6) and above, the advice given for variable declaration is “If possible, use const. Only use let if you know its value needs to change and never ever use var. (You can always go back and change a const to a let if it later turns out you need to change its value.)

Lets consider a common situation of pre ES6 frontend js code that you wrote in one of your web-application

1
var a=1; var b=2; var c=3; console.log(window.a,window.b,window.c);

and you refactoring it to ES6

1
const a=1; const b=2; const c=3; console.log(window.a,window.b,window.c);

The results are not what you expect and voila you learn something new today.
oops
Now consider this code, you can run this in node REPL or the browser console or run it as a script:

Example 1:

1
2
var a=1; var b=2; var c=3; console.log(this.a,this.b,this.c);
// 1 2 3

The same above code substitue the this with the window object when running in browser console, this is for better clarity( what clarity, you will know in a bit 😉 ):

Example 2:

1
2
var a=1; var b=2; var c=3; console.log(window.a,window.b,window.c);
// 1 2 3

Now being the good developer you are, if you refactor the code and heed to the advice of never using var, you are in for surprises:

Example 3:

1
2
3
4
const a=1; const b=2; const c=3; console.log(window.a,window.b,window.c);
// undefined undefined undefined
const a=1; let b=2; var c=3; console.log(a,b,c);
// 1 2 3

Example 4:

1
2
const a=1; let b=2; var c=3; console.log(window.a,window.b,window.c);
// undefined undefined 3

wait!! what’s happening here. Let’s break it down:

The common term used when describing the scope availability of let,const is that they are blocked scope and var is global scope or the scope enclosed in the given function.

The precise way of describing this concept is let and const declarations define variables that are scoped to the running execution context‘s LexicalEnvironment, and var are scoped in the VariableEnvironment.

Now going back to the Example 4 the variables a and b are not scoped to the window object but they are scoped to the LexicalEnvironment of the current execution context, now is there a way to get that current execution context and see what all it has? If you know a way, please enlighten me.

“Any fool can know. The point is to understand.”
-Albert Einstein