Замыкание — одна из главных сложностей в JavaScript, а также его особенность. Многие продвинутые приложения полагаются на замыкания.

1. Область видимости переменных

Чтобы понять замыкания, сначала нужно разобраться с особой областью видимости переменных в JavaScript.

Существует только два типа области видимости переменных: глобальные переменные и локальные переменные.

Особенность JavaScript в том, что функции могут напрямую читать глобальные переменные внутри себя, но локальные переменные внутри функции невозможно прочитать снаружи функции.

Примечание:При объявлении переменных внутри функции обязательно используйте команду var. Если этого не сделать, вы фактически объявите глобальную переменную!

2. Как прочитать локальные переменные внутри функции снаружи?

По разным причинам иногда нам нужно получить доступ к локальным переменным внутри функции. Однако, как упоминалось выше, при обычных обстоятельствах это невозможно! Этого можно добиться только окольными путями.

То есть внутри функции определяется другая функция.

function f1(){
    var n=999;
    function f2(){
        alert(n); // 999
    }
}

В приведённом выше коде функция f2 содержится внутри функции f1. В этом случае все локальные переменные внутри f1 видны для f2. Но обратное неверно; локальные переменные внутри f2 не видны для f1.

Это структура "цепочки областей видимости", уникальная для JavaScript.

Дочерние объекты будут искать уровень за уровнем, чтобы найти переменные всех родительских объектов. Поэтому все переменные родительского объекта видны дочерним объектам, но не наоборот.

Поскольку f2 может читать локальные переменные в f1, если мы вернём f2 в качестве возвращаемого значения, разве мы не сможем читать внутренние переменные f1 извне f1?

3. Понятие замыканий

Функция f2 в приведённом выше коде является замыканием.

Определения замыканий в различной профессиональной литературе очень абстрактны. Моё понимание таково: замыкание — это функция, которая может читать внутренние переменные других функций.

Поскольку в JavaScript только подфункции внутри функции могут читать локальные переменные, замыкание можно просто понимать как "функцию, определённую внутри другой функции".

Итак, по сути, замыкание — это мост, соединяющий внутреннюю часть функции с внешней частью функции.

4. Применения замыканий

Замыкания можно использовать во многих местах. У них есть два главных применения: одно — читать переменные внутри функции, как упоминалось ранее, а другое — постоянно хранить значения этих переменных в памяти, чтобы они не очищались автоматически после вызова f1.

Почему так? Причина в том, что f1 — родительская функция для f2, а f2 присвоена глобальной переменной. Из-за этого f2 всегда находится в памяти, а существование f2 зависит от f1, поэтому f1 также всегда находится в памяти и не будет собрана сборщиком мусора после завершения вызова.

Ещё одно примечательное место в этом коде — это"nAdd=function(){n+=1}"Эта строка. Во-первых, перед nAdd не используется ключевое слово var, поэтому nAdd — глобальная переменная, а не локальная. Во-вторых, значением nAdd является анонимная функция, и эта анонимная функция сама по себе также является замыканием, поэтому nAdd эквивалентна сеттеру, который позволяет извне функции управлять локальными переменными внутри функции.

5. На что следует обратить внимание при использовании замыканий

  • (1) Поскольку замыкания приводят к тому, что переменные в функциях сохраняются в памяти, потребление памяти велико, поэтому нельзя злоупотреблять замыканиями, иначе это вызовет проблемы с производительностью веб-страницы и может привести к утечкам памяти в IE. Решение — удалить все неиспользуемые локальные переменные перед выходом из функции.
  • (2) Замыкания могут изменять значения переменных внутри родительской функции извне родительской функции. Поэтому, если вы используете родительскую функцию как объект, замыкание как её публичный метод, а внутренние переменные как её приватные свойства, нужно быть осторожным и не изменять значения переменных внутри родительской функции необдуманно.

Оригинальная ссылка: https://www.cnblogs.com/cxying93/p/6103375.html