Закрытие JavaScript

внешний интерфейс программист Безопасность JavaScript

1. Что такое замыкание?

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

Примеры закрытия:

var count=10;//全局作用域 标记为flag1
function add(){
    var count=0;//函数全局作用域 标记为flag2
    return function(){
        count+=1;//函数的内部作用域
        alert(count);
    }
}
var s=add()
s();//输出1
s();//输出2

Возвращаемое значение add() является функцией.Когда s() вызывается в первый раз, это функция, которая выполняет возврат add(), который представляет собой следующую функцию:

function(){
        count+=1;//函数的内部作用域
        alert(count);
    }

То есть count + 1, в выводе откуда берется count?По правилам цепочки областей видимости, переменные, не объявленные в нижележащей области видимости, будут искаться на верхнем уровне, если будут найдены, то будут возвращаются, и если они не найдены, то продолжают поиск. , пока переменная окна, если переменной нет, не вернет undefined. Здесь, очевидно, count — это количество flag2 внутри функции,

var count=10;//全局作用域
function add(){
    //var count=0;注释掉了
    return function(){
        count+=1;//函数的内部作用域
        alert(count);
    }
}
var s=add()
s();//输出11
s();//输出12

Естественно, это не отражает природу замыкания, просто чтобы проиллюстрировать цепочку областей действия функции.Продолжить объяснение: первое выполнение, нет сомнений, что на выходе 1, что такое второй процесс? Продолжайте выполнять возвращаемый метод этой функции, или count+=1; а затем выведите count, здесь возникает проблема, разве вы не должны продолжить поиск, найти count=0; а затем вывести 1? Я не знаю, заметили ли вы проблему, то есть s() выполняет следующую функцию

function(){
        count+=1;//函数的内部作用域
        alert(count);
    }

То есть add() выполняется только один раз. Затем выполните s() дважды, значение count объявляется только один раз.

VAR S = Add (), функция только добавляет только здесь.

Все последующие выполнения — это s(). Откуда берется значение count во второй раз? Да, это переменная, оставшаяся после первого выполнения add.

(Как это возможно, переменная функции будет освобождена после выполнения, почему она все еще там? Вот проблема подсчета ссылок механизма сборки мусора).

""Если ссылка на переменную не равна 0, то она не будет утилизирована механизмом сборки мусора, а ссылка называется "".

Так как, когда s() выполняется снова, на переменную count, сгенерированную первым add(), ссылаются снова, поэтому счетчик не освобождается.В первый раз s() значение count равно 1, а во второй раз s( ), добавьте 1 к значению count, и оно, естественно, равно 2.

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

function add(){
    var count=0;//函数全局作用域
    return function(){
        count+=1;//函数的内部作用域
        alert(count);
    }
}
add()();//输出1
add()();//输出1

Это правда. Оба раза результат равен 1.

Кроме того, я думаю, что замыкание, о котором сказал Руань Ифэн, также очень лаконично: «Насколько я понимаю, замыкание — это функция, которая может считывать внутренние переменные других функций».

2 переменная область видимости

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

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

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

js-код

переменная n=999;

функция f1(){
оповещение (н);
} }

f1(); // 999

С другой стороны, локальные переменные внутри функции не могут быть естественным образом прочитаны вне функции.

js-код

функция f1(){
переменная n=999;
} }

оповещение(n); // ошибка

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

js-код

функция f1(){
п=999;
} }

f1();

оповещение(н); // 999

Иногда вам нужно получить локальные переменные внутри функции, а внутри функции определить функцию.

js-код

функция f1(){

п=999;

функция f2(){
оповещение(н); // 999
} }

} }

В приведенном выше коде функция f2 включена в функцию f1, и все локальные переменные внутри f1 видны f2. Но не наоборот, локальные переменные внутри f2 невидимы для f1. Это уникальная структура «цепной области» языка Javascript, и дочерний объект будет искать все переменные родительского объекта уровень за уровнем. Поэтому все переменные родительского объекта видны дочернему объекту, но не наоборот.

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

js-код

функция f1(){

п=999;

функция f2(){
оповещение (н);
} }

вернуть f2;

} }

вар результат=f1();

результат(); // 999

3. Замечания по использованию замыканий

1) Поскольку замыкание заставит переменные в функции храниться в памяти, потребление памяти очень велико, поэтому замыканием нельзя злоупотреблять, иначе это вызовет проблемы с производительностью веб-страницы, что может привести к утечкам памяти в IE. Обходной путь — удалить все неиспользуемые локальные переменные перед выходом из функции.

2) Закрытие будет вне родительской функции и изменит значение переменной внутри родительской функции. Таким образом, если вы используете родительскую функцию как объект, замыкание как ее открытый метод и внутреннюю переменную как ее частное значение, будьте осторожны, чтобы не ошибиться.

Измените значение переменной внутри родительской функции.

4. Использование замыканий

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

Как понять эту фразу? Пожалуйста, смотрите код ниже.


js-код

функция f1(){

переменная n=999;

nAdd=функция(){n+=1}

функция f2(){
оповещение (н);
} }

вернуть f2;

} }

вар результат=f1();

результат(); // 999

нДобавить();

результат(); // 1000

В этом коде результатом является замыкающая функция f2. Он запускался дважды, первый раз со значением 999 и второй со значением 1000. Это доказывает, что локальная переменная n в функции f1 хранится в памяти и не очищается автоматически после вызова f1.

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

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

Сама анонимная функция также является замыканием, поэтому nAdd эквивалентен установщику, который может работать с локальными переменными внутри функции вне функции.

5. Вывод

Понимание замыканий в JavaScript — единственный способ для продвинутых JS-программистов писать более безопасный и элегантный код.