Предисловие: это все еще вступительная статья. В JavaScript есть несколько очень важных языковых функций - объектов, прототипа наследования и закрытия. Среди них закрытие - это новая языковая функция для программистов, которые используют традиционный статический язык C/C ++. Эта статья начнется с примеров для представления языковых функций закрытия JavaScript и объединить некоторые языковые спецификации Ecmascript, позволяющие читателям более глубоко понимать закрытие.
Примечание. Эта статья представляет собой вступительную статью, а примеры материалов составлены в Интернете. Если вы мастер, вы можете выдвинуть технические предложения и мнения по статье. В этой статье обсуждается JavaScript, и вы не хотите сравнивать языки. Если вы, естественно, дискомфорт с JavaScript, пожалуйста, возьмите объезд.
Что такое закрытие
Что такое закрытие? Закрытие - это закрытие, которое является новой функцией, которой не имеют статических языков. Но закрытия - это не то, что настолько сложнее, что они непостижимы. Короче говоря, закрытие:
Закрытие - это набор локальных переменных функции, но эти локальные переменные будут продолжать существовать после возврата функции.
Закрытие - это «стек» функции и не выпускаются после возврата функции. Мы также можем понять, что эти стеки функций не выделяются в стеке, но выделяются на кучу.
При определении другой функции в функции будет сгенерировано закрытие
Второе определение выше - это первое дополнительное описание, которое извлекает объект предмет предмет первого определения - закрытие представляет собой набор «локальных переменных» функции. Просто к этой локальной переменной можно получить доступ после возврата функции. (Это не официальное определение, но это определение должно быть более благоприятным для вашего понимания закрытия)
Как локальные переменные, к ним можно получить доступ к коду в функции, и нет никакой разницы между этим и статическим языком. Разница между закрытиями заключается в том, что локальные переменные все еще могут быть доступны по коду вне функции после выполнения функции. Это означает, что функция должна вернуть «ссылку» на закрытие или назначить эту «ссылку» внешней переменной, чтобы убедиться, что локальные переменные в закрытии доступны по внешнему коду. Конечно, сущность, содержащая эту ссылку, должна быть объектом, потому что в JavaScript все остальные, кроме основных типов, являются объектами. К сожалению, Ecmascript не предоставляет соответствующих участников и методов для доступа к локальным переменным в закрытии. Однако в Ecmascript внутренняя функция, определенная в объекте функции, представляет собой локальную переменную, которая может напрямую получить доступ к внешним функциям. Благодаря этому механизму мы можем завершить доступ к закрытию следующим образом.
Кода -копия выглядит следующим образом:
приветствие функции (имя) {
var text = 'hello' + name; // локальная переменная
// Каждый раз, когда генерируется закрытие, и внутренний объект функции возвращается вызывающему абоненту
return function () {alert (text); }
}
var sayshello = приветствие ("закрытие");
SayShello () // Доступ к локальной переменной тексту через закрытие
Результатом выполнения приведенного выше кода является: Hello Closure, потому что после выполнения функции приветствия функция SayHello () может по -прежнему получить доступ к тексте локальной переменной, определенной в нем.
Хорошо, это эффект легендарного закрытия. Закрытие имеет много сценариев приложений и режимов в JavaScript, таких как Singleton, Power Constructor и другие режимы JavaScript, которые неотделимы от использования закрытия.
Модель закрытия ECMASCRIPT
Как Ecmascript реализует закрытие? Если вы хотите иметь глубокое понимание, вы можете получить спецификации ECMASCRIPT для исследований. Я дам здесь только простое объяснение, и контент также поступает из Интернета.
Когда работает функция скрипта ECMASCRIPT, каждая функциональная ассоциация имеет сценарий контекста выполнения (контекст выполнения), который содержит три части.
LexicalEnvironment
Переменная среда
Это связывание
Третий пункт этого обязательства не имеет ничего общего с закрытыми и не обсуждается в этой статье. Идентификатор переменной, используемый в грамматической среде для анализа процесса выполнения функции. Мы можем думать о грамматической среде как о объекте, который содержит два важных компонента, запись окружающей среды (рекодирование среды) и внешнюю ссылку (указатель). Запись среды содержит локальные переменные и переменные параметров, объявленные внутренне функцией, и внешние эталонные указывает на сценарий выполнения контекста объекта внешней функции. Это справочное значение является нулевым в глобальном сценарии контекста. Такая структура данных образует односторонний связанный список, каждый из которых указывает на сценарий внешнего контекста.
Например, модель закрытия в нашем примере выше должна быть такой. Функция Sayhello находится на самом низком уровне, верхний уровень - это приветствие функции, а самый внешний уровень - глобальная сцена. Как показано на рисунке ниже: Следовательно, когда называется Sayshello, Sayshello найдет значение локального текста переменной через контекстную сцену, поэтому переменная среда «Hello Crowur» (переменная среда) и грамматическая среда в основном одинакова. Для конкретных различий, пожалуйста, обратитесь к документу спецификации Ecmascript.
Образец колонки закрытия
В предыдущей статье я грубо понимаю, что такое закрытие JavaScript и как закрыты закрытия в JavaScript. Ниже мы поможем вам более глубоко понять закрытие, ориентируясь на некоторые примеры. Ниже приведены 5 примеров, а примеры из закрытия JavaScript для манекенов (зеркало). Пример 1: Локальные переменные в закрытии являются ссылками, а не копиями
Кода -копия выглядит следующим образом:
Функция shes667 () {
// локальная переменная, которая заканчивается закрытием
var num = 666;
var waysalert = function () {alert (num); }
num ++;
Возврат говорит, что;
}
var говорит, что Say667 ();
Сайлерт ()
Следовательно, результат выполнения должен появиться 667 вместо 666.
Пример 2: несколько функций связывают одно и то же закрытие, поскольку они определены в одной и той же функции.
Кода -копия выглядит следующим образом:
функция setupsomeglobals () {
// локальная переменная, которая заканчивается закрытием
var num = 666;
// хранить некоторые ссылки на функции как глобальные переменные
galertnumber = function () {alert (num); }
gincreaseNumber = function () {num ++; }
gsetNumber = function (x) {num = x; }
}
setupsomeglobals (); // назначать значения трем глобальным переменным
galertnumber (); // 666
gincreaseNumber ();
galertnumber (); // 667
GSETNumber (12); //
GalertNumber (); // 12
Пример 3: При назначении функций в цикле эти функции будут связываться с одинаковым закрытием
Кода -копия выглядит следующим образом:
Функция сборки (список) {
var result = [];
for (var i = 0; i <list.length; i ++) {
var item = 'item' + list [i];
result.push (function () {alert (item + '' + list [i])});
}
результат возврата;
}
Функциональный тест list () {
var fnlist = buildlist ([1,2,3]);
// Использование J только для предотвращения путаницы - может использовать I
for (var j = 0; j <fnlist.length; j ++) {
fnlist [j] ();
}
}
Результатом выполнения списка теста является то, что неопределенное окно Item3 выявляется три раза, потому что эти три функции связывают одно и то же закрытие, а значение элемента является последним вычисленным результатом, но когда я выпрыгивает из цикла, значение I составляет 4, поэтому результат списка [4] не определен.
Пример 4: Все локальные переменные внешних функций находятся в закрытии, даже если эта переменная объявлена после определения внутренней функции.
Кода -копия выглядит следующим образом:
Функция shayalice () {
var waysalert = function () {alert (alice); }
// локальная переменная, которая заканчивается закрытием
var alice = 'Привет, Алиса';
Возврат говорит, что;
}
var helloalice = sayalice ();
helloalice ();
Результатом выполнения является окно со всплывающим окном "Hello Alice". Даже если локальная переменная объявляет после того, как функция говорит, что локальная переменная все еще может быть доступна.
Пример 5: Создавайте новое закрытие каждый раз, когда вызывается функция
Кода -копия выглядит следующим образом:
Функция NewClosure (Somenum, Someref) {
// локальные переменные, которые оказываются в пределах закрытия
var num = somenum;
var anarray = [1,2,3];
var ref = someref;
возврат функции (x) {
num += x;
anarray.push (num);
Alert ('num:' + num +
'/nanarray' + anarray.toString () +
'/nref.somevar' + ref.somevar);
}
}
закрытие1 = newClosure (40, {somevar: 'Закрытие 1'});
Закрытие2 = NewClosure (1000, {SomeVar: 'Закрытие 2'});
Закрытие1 (5); // num: 45 anarray [1,2,3,45] ref: 'somevar closure1'
Закрытие2 (-10); // NUM: 990 ANARRAY [1,2,3,990] Ref: 'Comevar Closure2'
Применение закрытия
Синглтон одиночная часть:
Кода -копия выглядит следующим образом:
var singleton = function () {
var privateVariable;
функция privatefunction (x) {
... privateVariable ...
}
возвращаться {
FirstMethod: function (a, b) {
... privateVariable ...
},
SecondMethod: function (c) {
... privatefunction () ...
}
};
} ();
Эта единственная часть достигается через закрытие. Инкапсуляция частных членов и методов завершается через закрытие. Анонимная основная функция возвращает объект. Объект содержит два метода, метод 1 может использовать частные переменные, а метод 2 может получить доступ к внутренним частным функциям. Следует отметить «()», где заканчивается анонимная основная функция. Без этого '()' не может быть произведена единственная часть. Потому что анонимные функции могут возвращать только уникальные объекты и не могут быть вызваны в другом месте. Это метод использования закрытия для генерации отдельных частей.