I understand that let
prevents duplicate declarations which is nice.
let x;
let x; // error!
Variables declared with let
I found this explanation from Exploring ES6 book the best:
var-declaring a variable in the head of a for loop creates a single binding (storage space) for that variable:
const arr = []; for (var i=0; i < 3; i++) { arr.push(() => i); } arr.map(x => x()); // [3,3,3]
Every i in the bodies of the three arrow functions refers to the same binding, which is why they all return the same value.
If you let-declare a variable, a new binding is created for each loop iteration:
const arr = []; for (let i=0; i < 3; i++) { arr.push(() => i); } arr.map(x => x()); // [0,1,2]
This time, each i refers to the binding of one specific iteration and preserves the value that was current at that time. Therefore, each arrow function returns a different value.