With the release of ES6 came two new ways of declaring variables so now we have not only var but also let and const on top of that. Let's look at each one of them to see how they compare.

var

The good old var allows to declare variables that are scoped to the nearest function block, unless it's declared outside a function block. Then the variable is global to the entire application.

See how in the example below variable i is accessible from outside the loop it's declared in but within the same function. Also note how variable foo automatically gets assigned as a window property when declared globally.

var foo = 'Hey, I\'m global';

function bar() {
    for ( var i = 0; i < 5; i += 1 ) {
       // Do something
    }
    return i;
}

console.log(bar()); // 5
console.log(window.foo); // Hey, I'm global

Another interesting propery of var is that variable declarations, wherever they occur, are processed before any code is executed. Thus, as ridiculous as below example looks, it will actually return undefined rather than bar is not defined. This is because variable bar is declared before any code within that function is executed and thus when we return value bar, it is already declared but as you can see, not yet assigned with a value.

function foo() {
    return bar;
    if (true === false) {
		var bar = "bar";
	}
};

console.log(foo()); // undefined

let

let works just like variable declarations in most other languages where variables are declared by block scope rather than function scope. If declared globally i.e. outside any block, it behaves just like var with a difference that it does not get assigned as a window property. Thus, variables scope declared with let is just as big, or smaller, than that of var.

Note how in the below example, when we try to access i outside the block scope in which it was declared we get a reference error and also variable declared as global is not a property of a window object.

let foo = 'Hey, I\'m global';

function bar() {
    for ( let i = 0; i < 5; i += 1 ) {
       // Do something
    }
    return i;
}

console.log(bar()); // ReferenceError: i is not defined
console.log(foo); // Hey, I'm global
console.log(window.foo); // undefined

Remember the previous example with var where we returned bar before it was declared in the code? Well, that won't work with let and we will get a reference error. This type of behavior is more likely what you would expect from a programming language I reckon.

function foo() {
    return bar;
    if (true === false) {
		var bar = "bar";
	}
};

console.log(foo()); // ReferenceError: bar is not defined

const

I really like const for some reason. It's similar to final variable declaration in Java where it makes the variable impossible to reassign with a different value once the variable has already been assigned. Just like let, const variables are block scoped.

Note how in the below example we are unable to reassign foo with a new value. I found const to be very useful when declaring configuration options since they can't be reassigned.

const foo = 'hello';
foo = 'bye'; // TypeError: Assignment to constant variable.

Which one to use?

In short, use const whenever you can since it can't be reassigned. If you really need to change state, then use let. There is absolutely no reason to use var at this point.