Ограничения для меток с изменяющимся размером

Функция в JavaScript - это не просто ссылка на набор инструкций (как на языке C), но также включает скрытую структуру данных, которая состоит из ссылок на все нелокальные переменные, которые она использует (захваченные переменные). Такие функции из двух частей называются замыканиями. Каждая функция в JavaScript может считаться замыканием.

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

Поскольку все эти внешние переменные, на которые ссылается лексически вложенная функция, фактически являются локальными переменные в цепочке его лексически охватывающих функций (глобальные переменные можно считать локальными переменными некоторой корневой функции), и каждое отдельное выполнение функции создает новые экземпляры ее локальных переменных, из этого следует, что каждое выполнение функции, возвращающей ( или иным способом передать его, например, зарегистрировать его как обратный вызов), вложенная функция создает новое закрытие (с его собственным потенциально уникальным набором ссылочных нелокальных переменных, которые представляют его контекст выполнения).

Кроме того, он должен что локальные переменные в JavaScript создаются не в фрейме стека, а в куче и уничтожаются только тогда, когда никто не ссылается на них. Когда функция возвращается, ссылки на ее локальные переменные уменьшаются, но они все равно могут быть не равными нулю, если во время текущего выполнения они стали частью замыкания и по-прежнему ссылаются на его лексически вложенные функции (что может произойти, только если ссылки на эти вложенные функции были возвращены или иным образом переданы на некоторый внешний код).

Пример:

function foo (initValue) {
   //This variable is not destroyed when the foo function exits.
   //It is 'captured' by the two nested functions returned below.
   var value = initValue;

   //Note that the two returned functions are created right now.
   //If the foo function is called again, it will return
   //new functions referencing a different 'value' variable.
   return {
       getValue: function () { return value; },
       setValue: function (newValue) { value = newValue; }
   }
}

function bar () {
    //foo sets its local variable 'value' to 5 and returns an object with
    //two functions still referencing that local variable
    var obj = foo(5);

    //Extracting functions just to show that no 'this' is involved here
    var getValue = obj.getValue;
    var setValue = obj.setValue;

    alert(getValue()); //Displays 5
    setValue(10);
    alert(getValue()); //Displays 10

    //At this point getValue and setValue functions are destroyed
    //(in reality they are destroyed at the next iteration of the garbage collector).
    //The local variable 'value' in the foo is no longer referenced by
    //anything and is destroyed too.
}

bar();
0
задан Dávid Pásztor 22 March 2019 в 10:12
поделиться