Сбивающие с толку переменные области действия функции.

Когда мы используем ключевое слово var в ES5, объявляется переменная и область действия функции. Таким образом, приведенный ниже пример приводит к некоторому странному поведению:

var bar = 0;

function doSome(foo){
    if(foo){
        var bar = 1;
        return bar;
    }

    return bar;
}

doSome(false); // undefined  :(

Переменный подъем

Объявления переменных обрабатываются раньше всего в области видимости функции. Таким образом, предыдущий блок кода имеет больше смысла, когда он записывается по мере его обработки, например:

var bar = 0;

function doSome(foo){
    var bar;
    if(foo){
        bar = 1;
        return bar;
    }

    return bar;
}

doSome(false); // undefined

Такое поведение известно как подъем переменных и хорошо объяснено на MDN.

Здравствуйте, const

Когда мы хотим объявить постоянное значение, мы обычно ищем неизменяемость. В ES5, как правило, программисты определяют константы по соглашению, например так:

var NOT_SUPPOSED_TO_CHANGE = 'foo';

Однако это всего лишь соглашение, не обеспечивающее неизменности:

var NOT_SUPPOSED_TO_CHANGE = 'foo';

function changeConstant(val){
    NOT_SUPPOSED_TO_CHANGE  = 'bar';
    return NOT_SUPPOSED_TO_CHANGE;
}

changeConstant(NOT_SUPPOSED_TO_CHANGE); // 'bar'

Итак, с введением const в ES2015 мы получаем неизменяемые константы, верно?

const NOT_SUPPOSED_TO_CHANGE = 'foo';

NOT_SUPPOSED_TO_CHANGE = 'bar' // throws an exception "Assignment to constant variable"

Однако это не конец истории.

const AM_I_IMMUTABLE = { foo : 'bar' }; 

AM_I_IMMUTABLE.foo = 'baz'; // 'baz' ... WTF!?

Оказывается, константа на самом деле не означает неизменяемость. Это означает, что привязка значения не может быть повторена, и, как объясняется в статье, если вы ищете неизменность, вы можете попробовать Object.freeze().

Здравствуйте, позвольте

Как и в случае с var, когда мы привязываем значение к переменной, мы ожидаем, что ее значение может измениться.

function foo(val, doFoo){
    var iCanChange = 1;

    function bar(){
        if(doFoo){
            var iCanChange = 0;
            return iCanChange;
        }
        iCanChange += 5;
        return iCanChange;
    }       

    return val + iCanChange + bar();
}

foo(3, false);// NaN    
foo(3, true);// 104

Однако и let, и const имеют блочную область видимости, что означает, что вы получите довольно разные результаты:

function foo(val, doFoo){
    let iCanChange = 1;

    function bar(){
        if(doFoo){
            let iCanChange = 100;
            return iCanChange;
        }
        iCanChange += 5;
        return iCanChange;
    }       

    return val + iCanChange + bar();
}

foo(3, false);// 10 
foo(3, true);// 104

Явная область видимости блока

Благодаря статье Дэвида Уолша эта тема освещена очень подробно. Чтобы сделать ваши объявления let понятными и явными, вы можете объявить их в голых блоках.

let foo = 99;

{ let foo = 1;
    console.log(foo);
}

console.log(foo);
// outputs
// 1
// 99

Это пока все, что я могу найти по этому вопросу. Вперед.