Проблема с областью действия и замыканиями в JavaScript

Мой вопрос действительно больше касается области действия в JavaScript, а не закрытия.

Возьмем следующий код:

var f = function () {
    var n = 0;
    return function () {
        return n++;
    };
}();

console.log(f());
console.log(f());

Приведенный выше код выводит:

0
1

Как видно из приведенного выше кода, f (самовызываемый) возвращает функцию, создавая замыкание n.


Итак, он работает с анонимной функцией; таким образом, я попробовал это с именованной функцией:

var f2 = function () {
    return n++;
};

var f = function () {
    var n = 0;
    return f2;
}();

console.log(f2()); // <= [n is not defined]

Код выше не работает, ошибка n is not defined. Я предполагаю, что это проблема масштаба; но я не могу понять, почему именно;

Почему область видимости одинакова для анонимной внутренней функции, но не работает с именованной внешней функцией?

Кроме того, во втором примере я создаю замыкание?


person Andreas Grech    schedule 23.11.2009    source источник


Ответы (5)


Замыкание создается в первом примере, потому что код анонимной функции использует локальную переменную, объявленную вне анонимной функции.

Во втором примере область действия переменной n в функции f2 уже определена при объявлении функции. Создание локальной переменной с тем же именем не меняет смысла функции, а использование функции внутри другой функции не меняет ее области действия. Таким образом, функция не использует локальную переменную.

person Guffa    schedule 23.11.2009

область видимости в javascript является лексической /wiki/Scope_%28programming%29#Static_scoping_.28also_known_as_lexical_scoping.29

person user187291    schedule 23.11.2009

f2 никак не может понять, где взять переменную n.

В первом примере анонимная функция находится внутри функции f, во втором - снаружи (f2 вместо анонимной). Итак, f2 не может получить доступ к переменной n, потому что она находится в другой области видимости и недоступна (невидима). Попробуйте поместить объявление f2 внутри f.

person Roman    schedule 23.11.2009

Во втором примере вы не создаете закрытие, вы просто возвращаете глобальную переменную. f2 не закрывается, потому что он был объявлен в более общей (в данном случае глобальной) области видимости, а n объявлен в более конкретной области. Закрытие возможно вниз по «воронке» цепочки областей, а не вверх, и эффективно только тогда, когда все связанные объекты определены в одной области.

person Justin Johnson    schedule 23.11.2009

Мы могли бы переписать ваш второй пример, чтобы он работал с именованной функцией:

var f = function() {
    var n = 0;
    var f2 = function() {
        return n++;
    };
    return f2;
}();
console.log(f());
console.log(f());

Это выведет 0 и 1, как в вашем первом примере.

Как указывалось в других ответах, речь идет не о названной или анонимной функции, а о области действия n и f2. Поскольку в вашем примере вы объявили f2 вне f, у него не было доступа к переменной n, объявленной внутри области действия f.

person Ben Delarre    schedule 23.11.2009