Вау, разве вы не совсем смущены. Хорошо, я постараюсь объяснить закрытие как можно проще.
Во-первых, мы начнем с областей. Есть два типа областей:
- Блок прицелы
- Функция прицелы
Блок Объем начинается сразу же, когда это происходит в программе. С другой стороны, область действия не начинается до тех пор, пока не будет вызвана функция. Следовательно, несколько вызовов одной и той же функции приводят к созданию нескольких областей.
У JavaScript нет блоков. Он имеет только области функций. Следовательно, чтобы эмулировать область блока, нам нужно создать выражение функции и немедленно выполнить его. Это patttern называется immediately invoked function expression (IIFE) и это выглядит следующим образом:
(function() {
// this is the JS equivalent of a block scope
}());
Помимо блока областей и функции прицелы есть другой способ классификации областей. Поэтому мы также имеем:
- лексических прицелы
- Dynamic прицелы
Это различие касается только потому, что работать области блока прицелы всегда лексическая области видимости. JavaScript имеет только лексические области.
Чтобы понять разницу между лексическими областями и динамическими областями, нам нужно понять разницу между свободными и связанными переменными.
- Свободная переменная - это переменная, которая используется внутри функции, но не объявляется внутри этой функции.
- Переменная, объявленная внутри функции, называется связанной с этой функцией.
Рассмотрим следующую программу:
function add(x, y) {
return x + y; // x and y are bound to add
}
В приведенной выше программе переменные x
и y
связаны с функцией добавления, поскольку они объявлены в add
.
С другой стороны, переменные x
и y
в следующей программе свободны в функции add
, потому что они не объявлены в add
, но они используются в add
:
function add() {
return x + y; // x and y are free within add
}
Теперь свободные переменные являются проблемой , Они должны быть сопоставлены с некоторой ценностью, но какая ценность? Именно здесь появляются лексические и динамические области. Я не буду вдаваться в детали, но вы можете read about it on Wikipedia.
Области очень похожи на прототипное наследование. Когда начинается новая область, она наследует от родительской области, формируя цепочку областей, подобных целям прототипов в JavaScript.
Лексические области и динамические области различаются относительно того, к какой родительской области применяется новая область, наследующая форму.
- В лексическом масштабе область видимости новой функции наследуется от области действия этой функции (то есть ее лексической среды).
- В динамической области видимости новая область функций наследуется от области, в которой была вызвана эта функция (т. Е. Области вызова).
Поскольку JavaScript имеет только лексическое охват, мы не будем беспокоиться о динамическом охвате. Рассмотрим следующую программу:
var count = 0;
function incrementCount() {
return ++count;
}
(function() {
var count = 100;
alert(incrementCount()); // 1
}());
Здесь функция incrementCounter
имеет одну свободную переменную - count
. Поскольку JavaScript имеет лексическое охват count
будет отображаться в глобальную переменную count
вместо локального count
, объявленного в рамках IIFE. Следовательно, incrementCount
возвращает 1
, а не 101
.
Теперь закрытие работает только на языках, которые имеют лексическое охват.Рассмотрим следующую программу:
function getCounter() {
var count = 0;
return function() {
return ++count;
};
}
var counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
В приведенной выше программе функция, возвращаемая getCounter
является замкнутость относительно переменной count
, потому что:
- Переменная
count
свободна в возвращаемой функции (т.е. counter
).
- Функция перемещается за пределы области действия, в которой объявляется
count
.
Оба эти условия необходимы для того, чтобы функция называлась замыканием. Для получения дополнительной информации прочитайте следующий ответ: https://stackoverflow.com/a/12931785/783743
Теперь важно понять, что функция counter
по-прежнему будет называться закрытием, даже если она никогда не будет вызываться. Закрытие - это просто функция, которая закрывает над переменную (которая называется upvalue закрытия).
Когда мы вызываем getCounter
мы создаем новую область (назовем это сфера A
), и каждый раз, когда мы вызываем функцию, возвращенное getCounter
(т.е. counter
) мы создаем новую область, которая наследуется от объема A
. Это все. Никакого нового закрытия не создается.
Я не считаю, что замыкание создается дважды. Я думаю, по определению, это не будет сбор мусора, пока функция, которая ссылается на нее, также выходит за рамки. Если вы спрашиваете, будет ли второй вызов NephaliBuddha создать другой объект, тогда да, это будет. Он не зависит от того, который был создан ранее. – Hath995
Возможный дубликат [Как работают блокировки JavaScript?] (Http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – Paul
связанный с этим вопрос закрывается, я спрашиваю о внутренней области собственность не о закрытии –