There are 3 ways to declare a variable in Javascript: using one of the keywords var, const or let.

Prior to ES6, var used to be the only way to declare a variable. You had no other choice. However, it had some weird and unexpected behavior, which often resulted in hard to debug errors. Intuitively, you would think variable declared with var is block scoped. Variable declared in, for example, if statement, or a for loop, is visible only in the scope of that statement or loop.

Nope.

It is function scoped.

What this means is that a variable declared in a function would be visible in the entire function, even outside of if blocks or loops. If declared outside of functions, it becomes global;

 1var test1 = 1; // Global, as expected
 2
 3function testFunction() {
 4var test2 = 2; // Function scoped, as expected
 5
 6if (true) {
 7var test3 = 3; // Still function scoped
 8console.log(test3); // Logs 3, still ok
 9}
10
11console.log(test3); // Still logs 3 ???
12}

Let and var

Main difference between var and let is that let is block scoped. Block scoping means that a variable is visible only in the block scope it is declared, block being any block of code surrounded by curly braces {} such as a for loop or if statement, including any nested sub-blocks.

 1let test1 = 1; // Global, as expected
 2
 3function testFunction() {
 4let test2 = 2; // Function scoped, as expected
 5
 6if (true) {
 7let test3 = 3; // Still function scoped
 8console.log(test3); // Logs 3, still ok
 9}
10
11console.log(test3); // Uncaught ReferenceError: test3 is not defined
12}

Same example as previous one, this time all variables are declared with let instead of var. Now, if we use a variable declared with let in an if statement outside of it, we get a reference error.

Inside of a block scope, let is defined in it and all nested blocks, but not outside of it, while var is defined in the entire function, regardless of blocks.

Another main difference between var and let is that var is initialized with undefined by default. Let, on the other hand is not initialized at all until interpreter evaluates it. Accessing var before its declaration will return undefined, but let would result in reference error.

Const

Const is very similar to let, with some additional properties.

Initializing const is required, unlike let. Declaring another const with the same name is not possible.

1let foo; // ok
2foo = "foo"; // ok
3
4const bar; // SyntaxError: Missing initializer in const declaration
5const bar = "bar"; // ok

Const creates a read-only reference to the value. This does not mean a value cannot be changed, it means that you cannot re-assign to the same identifier again. Also, it does not mean the value becomes immutable. It still can be changed, but not by re-assigning. For example, you could change properties of an object, or remove from an array, but not by assigning new object or an array.

Conclusion

Var is slowly becoming a thing of the past. Most browsers support let and const today, and are much easier to work with than var. Some widely used libraries and old apps still use var, so it is still widespread, but for new projects it is rarely used. It is much safer to use const by default, only changing it to let when re-assigning is necessary.

References