var: variables declared using the var keyword are scoped to the function in which they are created, or if created outside of any function, to the global scope.
let & const: are block-scoped, meaning they are only accessible within the nearest set of curly braces (function, if-else block, for loop, etc)
function foo() { // All variables are accessible within functions. var bar = 'bar'; let baz = 'baz'; const qux = 'qux'; console.log(bar); // bar console.log(baz); // baz console.log(qux); // qux}console.log(bar); // ReferenceError: bar is not definedconsole.log(baz); // ReferenceError: baz is not definedconsole.log(qux); // ReferenceError: qux is not defined
if (true) { var bar = 'bar'; let baz = 'baz'; const qux = 'qux';}// var declared variables are accessible anywhere in the function scope.console.log(bar); // bar// let and const defined variables are not accessible outside of the block they were defined in.console.log(baz); // ReferenceError: baz is not definedconsole.log(qux); // ReferenceError: qux is not defined
var, let and const declared variables are all hoisted. var declared variables are auto-initialized with an undefined value. However, let and const variables are not initialized and accessing them before the declaration will result in a ReferenceError exeption because they are in a "temporal dead zone" from the start of the block until the decleration is processed.
console.log(foo); // undefinedvar foo = 'foo';console.log(baz); // ReferenceError: can't access lexical declaration 'baz' before initializationlet baz = 'baz';console.log(bar); // ReferenceError: can't access lexical declaration 'bar' before initializationconst bar = 'bar';