Закрытие является важной функцией в JavaScript, и их самая большая функция - сохранить информацию во время работы функции. В JavaScript многие функции закрытия получены из цепочки объема во время вызовов функций.
Цепочка функций объектов и переменных вызовов и переменных
Для каждого вызова функции в JavaScript JavaScript создаст локальный объект для хранения локальных переменных, определенных в функции; Если внутри функции есть вложенная функция, JavaScript определит вложенный локальный объект на уже определенном локальном объекте. Для функции существует столько слоев вложенных определений функций, сколько и многих слоев вложенных местных объектов, как и их. Этот локальный объект называется «объект вызова функции» («Объект вызова» в Ecmascript 3 и был переименован в «Запись декларативной среды» в Ecmascript 5, но я лично думаю, что имя в Ecmascript 3 легче понять). В качестве примера используются следующие вызовы функции:
Кода -копия выглядит следующим образом:
функция f (x) {
var a = 10;
вернуть*x;
}
Консоль.log (f (6)); // 60
В этом простом примере, когда функция f () вызывается, JavaScript создаст объект вызова функции f () (давайте назовем это f_invokeobj). Внутри объекта f_invokeobj есть два свойства: a и x; Когда f () запускается, значение a составляет 10, а значение x - 6, поэтому окончательный результат возврата - 60. Иллюстрация заключается в следующем:
При наличии функциональных гнездования JavaScript создаст несколько объектов вызова функции:
Кода -копия выглядит следующим образом:
функция f (x) {
var a = 10;
вернуть a*g (x);
функция g (b) {
возврат B*B;
}
}
Консоль.log (f (6)); // 360
В этом примере при вызове функции f () JavaScript создаст объект вызова функции f () (f_invokeobj), который имеет два атрибута a и x, а значение a равно 10, а значение x - 6; При запуске f () JavaScript будет проанализировать и определять функцию g () в функции f () и создаст объект вызова g () (g_invokeobj), который имеет атрибут B, а значение b такое же, как и параметр передаваемого, поэтому результат окончательного возврата - 360. Иллюстрация является следующей:
Как видите, объект вызова функции образует цепочку. Когда встроенная функция g () работает и необходимо получить значение переменной, она начнет поиск из самого последнего объекта вызова функции. Если его нельзя найти, поиск в дальнейшем объекте вызова вдоль цепочки цепочки функции вызова, которая представляет собой так называемую «цепочку переменных». Если одна и та же переменная появляется в двух объектах вызова функции, функция будет принять значение переменной в ближайшем к ней объекту вызова:
Кода -копия выглядит следующим образом:
функция f (x) {
var a = 10;
вернуть a*g (x);
функция g (b) {
var a = 1;
вернуть b*b*a;
}
}
Console.log (f (6)); // 360, а не 3600
В приведенном выше примере переменная A имеет разные значения в вызовом объекте (g_invokeobj) функции g () и вызывающего объекта (f_invokeobj) функции f (). При запуске функции g () значение, используемое внутри функции g (), равно 1, в то время как значение, используемой вне функции g (), равна 1. Цепочка объекта вызова функции в настоящее время выглядит следующим образом:
Что такое закрытие?
Все функции в JavaScript являются объектами, и при определении функций будет сгенерирована соответствующая цепочка функций. Определение функции соответствует цепочке функций вызывает объекты. Пока существует объект функции, существует соответствующий объект вызова функции; После того, как функция больше не используется, соответствующий объект вызова функции будет собран мусором; и эта комбинация функционального объекта и цепочка функционального объекта вызовов называется «закрытие». В приведенных выше примерах функции f () и функции g () существует два закрытия: объект функции f () и объект f_invokeobj образуют закрытие, а объект функции g () и цепочка объекта g_invokeobj-f_invokeobj образуют второе закрытие. Когда функция g () выполняется, поскольку функция g () больше не используется, закрытие g () собирается мусор; Затем, когда функция f () выполняется, закрытие F () также собирается мусор по той же причине.
Из определения закрытия мы можем сделать вывод: все функции JavaScript являются закрытием после определения, потому что все функции являются объектами, и все функции также имеют соответствующие цепочки объектов вызова после выполнения.
Тем не менее, то, что делает закрытие, действительно является случай вложенных функций. Поскольку встроенная функция определяется только при запуске внешней функции, значение переменной, хранящее в закрытии встроенной функции (особенно значение локальной переменной внешней функции) является значением во время этого прогона. Пока встроенный объект функции все еще существует, его закрытие все еще существует (значение переменной в закрытии не будет изменяться), тем самым достигая цели сохранения информации процесса, выполняемого функцией. Рассмотрим следующий пример:
Кода -копия выглядит следующим образом:
var a = "снаружи";
функция f () {
var a = "Inside";
Функция g () {return a;}
возврат G;
}
var result = f ();
console.log (result ()); // Внутри
В этом примере, когда функция f () выполняется, функция g () определяется, и создается закрытие функции g (). Закрытие g () содержит цепочку объекта g_invokeobj-f_invokeobj, поэтому значение переменной a во время выполнения функции f () сохраняется. Когда оператор консоли.log () выполняется, закрытие g () все еще существует, потому что объект функции G все еще существует; При запуске этого все еще существующего объекта G Function JavaScript будет использовать все еще существующее закрытие G () и получить от него значение переменной a («внутри»).