Лексическая область видимости

Где движок js смотрит запрашиваемые переменные?

Внутри области видимости, где были запрошены, и внутри всех наружных областей видимости.

function f1() {
    var a = 1;

    function f2() {
        var b = 2;

        function f3() {
            var c = 3;
            console.log(a);
        }
    }
}

Каждая из этих функций образует область видимости. Область видимост f2 вложена в область видимости f1 поэтом f2 имеет доступ и к своей области видимости и к наружной. В то время как f1 имеет доступ только к своей области видимости и к глобальной.

Например мы хотим в функции f3 вывести значение переменной a. Сначала js движок будет искать эту переменную в текущей области видимости. Если не найдет, то будет смотреть во внешней области видимости, в нашем примере — это f2. Если переменная не обнаружится и здесь, то поиско продолжится вплоть до глобальной области видимости. Если не найдет и в глобальной области видимости, то выдаст нам ошибку — ReferenceError: a is not defined.

Старайтесь всегда использовать strict mode — для того чтобы избежать многих ошибок. В данном случае. Если вы вдруг укажите переменную без ключевого слова var, let или const и будет не в strict mode, то переменная сохранится в глобальную область видимости, где бы вы её не указали.

Функции vs. блочная область видимости

В ES6 появилась блочная область видимости. Теперь для того чтобы ограничить область видимости нужно всего лишь указать перед перменной let или const. Теперь эта переменная закрыта в области видимости, которая ограничивается блоком (то что в фигурных скобках).

Теперь всегда старайтесь использовать let или const вместо var.