1. var

Scope:
var is function-scoped, meaning the variable is accessible throughout the entire function in which it is declared (even before the declaration, due to hoisting). If declared outside of any function, it’s globally scoped.

Reassignable:
You can reassign values to var.

Hoisting:
Variables declared with var are hoisted to the top of their scope, meaning they are available even before their declaration line, but their value is undefined until initialized.

Example:

function exampleVar() {
  console.log(a); // undefined (due to hoisting)
  var a = 5;
  console.log(a); // 5
}
exampleVar();

2. let

Scope:
let is block-scoped, thus being accessible strictly within the set of brackets ({ }) in which it is declared.

Reassignable:
You can reassign values to let.

Hoisting:
Variables declared with let are not hoisted (raised) to the top of their scope, therefore they are not available until the parser reaches them in the code.

Example:

function exampleLet() {
  // console.log(a); // Error: Cannot access 'a' before initialization
  let a = 5;
  console.log(a); // 5
}
exampleLet();

3. const

Scope:
const is also block-scoped, similar to let.

Reassignable:
Variables declared with const cannot be reassigned after initialization. However, if the value is an object or array, the contents (properties/elements) can still be modified.

Hoisting:
Like let, const variables are hoisted but are not initialized until the line where they are declared.

Example:

function exampleConst() {
  const a = 10;
  // a = 20; // Error: Assignment to constant variable.
  console.log(a); // 10
  
  const obj = { name: 'John' };
  obj.name = 'Doe'; // Allowed: Changing properties of an object
  console.log(obj); // { name: 'Doe' }
}
exampleConst();

Key Differences in Summary:

Feature var let const
Global Scope
Functional Scope
Block Scope
Cab be re-assigned
Cab be re-decleared