Автор оригинала: FreeCodeCamp Community Member.
Полностью понимание закрытия может показаться правом отрывка, чтобы стать разработчиком JavaScript.
Есть причина, по которой может быть трудно понять ощущение замыкания – потому что их часто преподают назад Отказ Возможно, вы были преподаваться тому, что такое замыкание, но вы можете не понять, как они полезны для среднего разработчика или в вашем собственном коде.
Так почему же важно замыкание в нашем повседневном коде JavaScript?
Вместо того, чтобы увидеть замыкание как тему, которая должна запомниться на какую-то поп-викторину, давайте посмотрим, какие ряды шагов могут привести нас к тому, чтобы увидеть закрытие в первую очередь. Как только мы посмотрим, что они есть, мы раскроемся, зачем вам стоит закрытие, чтобы вы узнали и воспользуйтесь в вашем коде JavaScript.
Хотите просмотреть этот урок? В этом руководстве является частью BootCamp 2020 JS, более 4+ часовой курс, который показывает, как быть экспертом JavaScript через тонны практических, безводных уроков. Получите мгновенный доступ к Bootcamp JS здесь Отказ
Видя закрытие в дикой природе?
Допустим, мы делаем приложение клон ведущего блога среднего размера, и мы хотим, чтобы каждый пользователь мог любить разные сообщения.
Всякий раз, когда пользователь нажимает на кнопку «Нравится», его значение будет увеличиваться на один раз.
Подумайте об этом, как кнопка «Среднего хлопка»:
Функция, которая будет обрабатывать увеличение количества на 1 каждый раз, называется HandleLikePost
И мы отслеживаем количество лайков с переменной именем likeCount
:
// global scope let likeCount = 0; function handleLikePost() { // function scope likeCount = likeCount + 1; } handleLikePost(); console.log("like count:", likeCount); // like count: 1
Всякий раз, когда пользователь любит пост, мы называем HandleLikePost
И это увеличивает наш likeCount
к 1.
И это работает, потому что мы знаем, что функции могут получить доступ к переменным за пределами себя.
Другими словами, Функции могут получить доступ к любым переменным, определенным в любой родительской области Отказ
Однако есть проблема с этим кодом. С likeCount
находится в глобальном масштабе, а не в какой-либо функции, likeCount
это глобальная переменная. Глобальные переменные могут быть использованы (и изменены) любым другим битом кода или функции в нашем приложении.
Например, что если после нашей функции мы ошибочно установили наши likeCount
до 0?
let likeCount = 0; function handleLikePost() { likeCount = likeCount + 1; } handleLikePost(); likeCount = 0; console.log("like count:", likeCount); // like count: 0
Естественно, likeCount
никогда не может быть увеличен от 0.
Когда только одна функция нуждается в данном элементе данных, ему просто нужно существовать локально, то есть в этой функции.
Теперь давайте принесем likeCount
В нашей функции:
function handleLikePost() { // likeCount moved from global scope to function scope let likeCount = 0; likeCount = likeCount + 1; }
Обратите внимание, что есть более короткий способ написать линию, где мы увеличиваем likeCount
Отказ Вместо того, чтобы сказать likeCount
равно предыдущему значению likeCount
И добавьте тому подобное, мы можем просто использовать тому подобное:
function handleLikePost() { let likeCount = 0; likeCount += 1; }
И для этого, чтобы работать как раньше и получите как значение Count, нам также нужно принести наши console.log
в функцию также.
function handleLikePost() { let likeCount = 0; likeCount += 1; console.log("like count:", likeCount); } handleLikePost(); // like count: 1
И это все еще работает должным образом, как и раньше.
Итак, теперь пользователи должны быть в состоянии понравиться пост столько раз, сколько они хотят, поэтому давайте позвоним HandleLikePost
Еще несколько раз:
handleLikePost(); // like count: 1 handleLikePost(); // like count: 1 handleLikePost(); // like count: 1
Однако, когда мы запустим этот код, есть проблема.
Мы ожидаем увидеть likeCount
Держите увеличение, но мы просто видим 1 каждый раз. Это почему?
Возьмите секунду, посмотрите на наш код и попытайтесь объяснить, почему наша likeCount
больше не увеличивается.
Давайте посмотрим на наш HandleLikePost
Функция и как это работает:
function handleLikePost() { let likeCount = 0; likeCount += 1; console.log("like count:", likeCount); }
Каждый раз, когда мы его используем, мы воссоздаем это likeCount
Переменная, которая дается начальное значение 0.
Неудивительно, что мы не можем отслеживать количество звонков функций! Он продолжает устанавливаться на 0 каждый раз, затем он увеличивается на 1, после чего функция завершается запущенной.
Итак, мы застряли здесь. Наша переменная должна жить внутри HandleLikePost
Функция, но мы не можем сохранить счет.
Нам нужно что-то, что позволяет нам сохранить или помнить likeCount
Значение между функционными вызовами.
Что, если мы попробоваем что-то, что может выглядеть немного странно на первых – что, если мы попробовали вкладывать другую функцию в нашу функцию:
function handleLikePost() { let likeCount = 0; likeCount += 1; function() { } } handleLikePost();
Здесь мы собираемся назвать эту функцию Addlike
Отказ Причина? Потому что это будет нести ответственность за увеличение likeCount
Переменная сейчас.
И обратите внимание, что эта внутренняя функция не должна иметь имя. Это может быть анонимная функция. В большинстве случаев это. Мы просто даем ему имя, поэтому мы можем проще говорить об этом и что это делает.
Addlike
Теперь будет нести ответственность за увеличение нашего likeCount
Итак, мы переместим линию, где мы увеличиваем на 1 в нашу внутреннюю функцию.
function handleLikePost() { let likeCount = 0; function addLike() { likeCount += 1; } }
Что если мы должны были назвать это Addlike
Функция в HandleLikePost
?
Все, что произойдет, это то, что Addlike
будет увеличиваться наш likeCount
, но все же likeCount
Переменная была бы уничтожена. Так что опять же, мы теряем нашу ценность, и результат 0.
Но вместо того, чтобы звонить Addlike
В пределах его прилагающей функции, что, если мы назвали это вне функции? Это кажется даже незнакомцем. И как бы мы сделаем это?
На данный момент мы знаем, что функции возвращаемых значений. Например, мы могли бы вернуть наше likeCount
Значение в конце HandleLikePost
Передать его в другие части нашей программы:
function handleLikePost() { let likeCount = 0; function addLike() { likeCount += 1; } addLike(); return likeCount; }
Но вместо этого давайте вернемся likeCount
внутри Addlike
а затем вернуть Addlike
Функция сама:
function handleLikePost() { let likeCount = 0; return function addLike() { likeCount += 1; return likeCount; }; // addLike(); } handleLikePost();
Теперь это может выглядеть причудливым, но это разрешено в JS. Мы можем использовать функции, такие как любое другое значение в JS. Это означает, что функция может быть возвращена из другой функции. Возвращая внутреннюю функцию, мы можем назвать его снаружи его прилагающей функции.
Но как бы мы это сделаем? Подумайте об этом на минуту и посмотрите, можете ли вы понять это …
Во-первых, чтобы лучше посмотреть, что происходит, давайте Console.log (HandleLikePost)
Когда мы называем это и посмотрим, что мы получаем:
function handleLikePost() { let likeCount = 0; return function addLike() { likeCount += 1; return likeCount; }; } console.log(handleLikePost()); // ƒ addLike()
Неудивительно, что мы получаем Addlike
Функция зарегистрирована. Почему? Потому что мы возвращаем это, в конце концов.
Называть это, мы не могли бы просто поставить его в другую переменную? Как мы только что сказали, функции могут быть использованы как любое другое значение в JS. Если мы сможем вернуть его из функции, мы можем поставить его в переменной тоже. Итак, давайте положим его в новую переменную под названием как
:
function handleLikePost() { let likeCount = 0; return function addLike() { likeCount += 1; return likeCount; }; } const like = handleLikePost();
И, наконец, давайте позвоним как
Отказ Мы сделаем это несколько раз и console.log
каждый результат:
function handleLikePost() { let likeCount = 0; return function addLike() { likeCount += 1; return likeCount; }; } const like = handleLikePost(); console.log(like()); // 1 console.log(like()); // 2 console.log(like()); // 3
Наше likeCount
наконец сохранился! Каждый раз, когда мы называем как
, likeCount
увеличивается из его предыдущего значения.
Так что в мире произошло здесь? Ну, мы поняли, как позвонить Addlike
функционируйте из-за пределов объема, в которой он был объявлен. Мы сделали это, вернув внутреннюю функцию из внешнего и хранив ссылку на него, названной как
, чтобы назвать это.
Как работает закрытие, строка?
Так что это была наша реализация, конечно, но как мы сохранили ценность likeCount
между вызовами функций?
function handleLikePost() { let likeCount = 0; return function addLike() { likeCount += 1; return likeCount; }; } const like = handleLikePost(); console.log(like()); // 1
-
HandleLikePost
Наружная функция выполнена, создавая экземпляр внутренней функцииAddlike
; Эта функция закрывается над переменнойlikeCount
, который является одним объемом выше. - Мы позвонили
Addlike
функционируйте из-за пределов объема, в которой он был объявлен. Мы сделали это, вернув внутреннюю функцию из внешнего и хранив ссылку на него, названнойкак
, чтобы назвать это. - Когда
как
Функция заканчивается, как правило, мы ожидали, что все его переменные будут собраны мусор (удалены из памяти, что является автоматическим процессом, который делает компилятор JS). Мы ожидаем, что каждыйlikeCount
уйти, когда функция сделана, но они этого не делают.
Что это причина? Закрытие Отказ
Поскольку экземпляры внутренних функций все еще живы (назначены нравиться ) закрытие все еще сохраняет подобный Переменные.
Вы думаете, что имея функцию, написанную в другой функции, просто будет похоже на функцию, написанную в глобальном объеме. Но это не так.
Вот почему закрытие делает функции настолько мощными Поскольку это специальное свойство, которое не присутствует ни в чем другом на языке.
Срок службы переменной
Чтобы улучшить замыкание, мы должны понимать, как JavaScript обрабатывает переменные, которые создаются. Возможно, вы пообщались, что происходит с переменными, когда вы закрываете свою страницу или перейдите на другую страницу в приложении. Как долго живут переменные?
Глобальные переменные живут до тех пор, пока программа не будет отброшена, например, при закрытии окна. Они вокруг для жизни программы.
Тем не менее, местные переменные имеют короткую жизнь. Они созданы, когда функция вызывается, и удаляется при завершении функции.
Так раньше, где likeCount
была просто локальная переменная, когда функция была запущена. Переменная LikeCount была создана в начале функции, а затем уничтожена после завершения выполнения.
Закрытия не снимки – они поддерживают локальные переменные
Иногда заявляет, что закрытия JavaScript похожи на снимки, изображение нашей программы в определенный момент времени. Это заблуждение, которое мы можем разветься, добавив другую функцию нашей функциональности кнопки.
Допустим, в некоторых редких случаях мы хотим позволить пользователям «удвоить» пост и увеличить likeCount
на 2 за раз вместо 1.
Как бы мы добавили эту функцию?
Другой способ пропускания ценностей к функции, конечно, через аргументы, которые работают так же, как локальные переменные.
Давайте пройдем в аргумент, называемый шагом к функции, что позволит нам обеспечить динамическое изменяемое значение для увеличения нашего подсчета вместо жесткого кодированного значения 1.
function handleLikePost(step) { let likeCount = 0; return function addLike() { likeCount += step; // likeCount += 1; return likeCount; }; }
Далее, давайте попробуем сделать специальную функцию, которая позволит нам удвоить, как наши посты, DoubleLike. Мы пройдем в 2, как наше шаг
Значение, чтобы сделать это, а затем попробуйте позвонить как наших функций, как
и DoubleLike
:
function handleLikePost(step) { let likeCount = 0; return function addLike() { likeCount += step; return likeCount; }; } const like = handleLikePost(1); const doubleLike = handleLikePost(2); like(); // 1 like(); // 2 doubleLike(); // 2 (the count is still being preserved!) doubleLike(); // 4
Мы видим likeCount
также сохраняется для DoubleLike
Отказ
Что тут происходит?
Каждый экземпляр внутреннего Addlike
Функция закрывается по обоим likeCount
и шаг
Переменные из его внешнего HandleLikePost
Область функции. шаг
Остается то же самое со временем, но счет обновляется при каждом вызове этой внутренней функции. Поскольку закрытие находятся над переменными, а не только снимки значений, эти обновления сохраняются между вызовами функций.
Итак, что делает этот код нам – тот факт, что мы можем пройти в динамических значениях, чтобы изменить результат нашей функции? Что они все еще живы! Закрытие сохраняет локальные переменные в живых из функций, которые должны были уничтожить их давно.
Другими словами, они не являются статическими и неизменными, такие как снимок значений замкнутых переменных в одной точке во времени, сохраняют переменные и обеспечивают им активную связь. В результате мы можем использовать замыкание могут наблюдать или сделать обновления этих переменных со временем.
Что такое закрытие, точно?
Теперь, когда вы видите, насколько полезно закрытие, есть два критерия для чего-то, чтобы быть закрытием, оба которых вы видели здесь:
- Закрытия являются свойством функций JavaScript и только функции. Ни один другой тип данных не имеет их.
- Чтобы наблюдать замыкание, вы должны выполнить функцию в другом объеме, чем в том, что эта функция была первоначально определена.
Почему вы должны знать замыкание?
Давайте ответим на оригинальный вопрос, который мы отправились к ответу. Исходя из того, что мы видели, пауза и нанесите удар при ответе на этот вопрос. Почему мы должны заботиться о закрытиях, как разработчики JS?
Застегивание для вас и вашего кода, потому что они позволяют «запомнить» значения, которые являются очень мощной и уникальной функцией на языке, которые обладают только функциями.
Мы видели это прямо здесь в этом примере. В конце концов, какое использование является как переменная подсчета, которая не помнит лайков? Вы часто встречаете это в вашей карьере JS. Вам нужно как-то удерживать некоторое значение и, вероятно, сохранит его отдельно от других значений. Что ты используешь? Функция. Почему? Чтобы отслеживать данные с течением времени с закрытием.
И с этим вы уже шаг впереди другие разработчики.
Наслаждайтесь этим постом? Присоединяйтесь к React BootCamp
React Bootcamp Занимает все, что вы должны знать о изучении реагирования и связки в один комплексный пакет, включая видео, обманывать, плюс специальные бонусы.
Получить инсайдерскую информацию сотни разработчиков уже использовалось для освоения реагирования, находить работу своей мечты и контролировать свое будущее:
Нажмите здесь, чтобы быть уведомленным, когда он открывается