Warto jeszcze wspomnieć, że JS ma coś takiego co się zwie 'hoisting' (dotyczy deklaracji)
foo(); // Zauważ, że wykonujemy 'foo' przed zadeklarowaniem. To się wykona poprawnie.
function foo() {
...
}
natomiast:
bar(); // TypeError: bar is not a function. Tutaj hoisting nie zadziała.
var bar = function bar() {
...
}
Co do let i const - wprowadzają one zakres blokowy (w JS mamy 'domyślnie' zakres w stosunku do funkcji).
function baz() {
if(true) {
let someLet = 'let';
var someVar = 'var';
}
console.log(someVar); // 'var' <- var ma zakres funkcji
console.log(someLet); // ReferenceError: someLet is not defined
}
Co do const, to tak jak napisał orkin - zapobiega nadpisaniu, czyli:
function foo() {
const SOME_VALUE = 21;
SOME_VALUE = 22; // TypeError: invalid assignment to const `SOME_VALUE'
}
ale mała uwaga, np.:
function foo() {
const SOME_ARR = [1, 2, 3];
SOME_ARR.push(4); // Ok, można dodać do tablicy kolejny element.
}
To z czym powinieneś się jeszcze zapoznać, to this w funkcji klasycznej vs funkcji strzałkowej.
A jeśli idzie o let i const to TDZ (the temporal dead zone).