Les variables déclarées sans le mot-clé var ont une portée globale: leur durée
de vie est celle de l'application.

<script>
function fonc() { 
    a = 1; // la portée est globale 
    var b = 2; // la portée est locale 
}
</script>
D'après la doc "L'instruction let permet de déclarer une variable dont la portée est celle du bloc courant, éventuellement en initialisant sa valeur." La portée de let est au niveau du block. Let est décrite comme "variable locale"
<script>
let a = 1;

if (a === 1) {
  let a = 2;

  console.log(a);
  // expected output: 2
}

console.log(a);
// expected output: 1
</script>
La portée de var est la fonction. La portée de let est le block.

Dans la portée globale

La portée de ces variables est différente quand utilisées en dehors d'une fonction:
<script>
let a = 'abc';  // globally scoped
var d = 'def'; // globally scoped

console.log(window.a); // undefined
console.log(window.c); // 'def'
</script>
La variable let n'apparait pas.

Dans la portée d'une fonction

Leur accessibilité est identique
<script>
function foo() {
    let foo = 'bien'; //function block scoped
    var bar = 'bon'; //function block scoped
}
</script>

Dans la portée d'un block

Le let n'est visible que dans la portée du block.
<script>
function test() {
    //a n'est pas accessible ici

    for(let a=0; a<5; a++) {
        // a n'est accessible qu'ici (et les parenthèses du for)
        // et c'est une nouvelle variable à chaque passe
    }

    //a n'est pas accessible ici
}
</script>
<script>
function testvar() {
    //a est accessible ici

    for(var a=0; a<5; a++) {
        //a est accessible dans toute la fonction
    }

    //a est accessible ici
}
</script>

Conclusion

var: portée niveau fonction let: portée niveau block