Что такое закрытие в JavaScript? Почему закрытия имеют значение? Как вы используете закрытие?

Поскольку страница MDN о закрытии определяет это очень хорошо, я не собираюсь изобретать велосипед здесь:

Замыкание - это комбинация объединенной (заключенной) функции со ссылками на ее окружающее состояние (лексическая среда).

Давайте немного раскроем эту концепцию.

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

Во многих случаях лексическая среда функции - это просто глобальная область видимости, потому что именно там вы ее создали. Не волнуйтесь, в этом нет ничего плохого.

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

Вот пример:

Здесь у нас есть rocket функция, у которой есть несколько локальных переменных, и внутренняя fly функция. Когда я вызываю rocket, он возвращает уникальный экземпляр объекта с функцией fly, хранящейся внутри этого объекта (строка 15). Важно отметить, что я еще не звоню fly. Я просто возвращаю объект, внутри которого есть функция fly.

Каждый раз, когда я вызываю функцию rocket, я возвращаю отдельный экземпляр функции fly, и этот экземпляр fly фактически удерживает свой собственный экземпляр своей лексической среды даже после rocket завершил работу.

В этом и заключается сила закрытия: каждый раз, когда я вызываю rocket, я создаю экземпляр fly, который имеет постоянную ссылку на уникальную лексическую среду.

Вы можете увидеть, как этот конкретный вариант использования может быть ценным, если вы пытаетесь сделать что-то объектно-ориентированное. Мы инкапсулировали состояние и поведение в постоянной и многоразовой манере! И мы не использовали class, constructor, this или new. Как насчет этого.

Еще одна приятная вещь в объектно-ориентированном программировании таким образом заключается в том, что ваше состояние на самом деле является частным и недоступным по сравнению с тем, когда вы используете синтаксис класса из ES2015. Вы не можете получить доступ к имени ракеты с помощью sputnik._name (если вы не добавили его к возвращаемому объекту rocket в строке 15, но вы не должны этого делать).

Возможность сохранять частное государство по-настоящему недоступным - это действительно хорошо. Он сообщает читателям, как следует и не следует использовать эту функцию. Сохраняйте частные переменные в секрете. Это также дает вам возможность реализовать настоящую парадигму «только чтение», если вы захотите.

Например:

Я добавил доступ по имени в объект, возвращаемый rocket в строках 17–19, используя синтаксис get. Теперь я могу прочитать свойство _name, но не могу его изменить. Это именно то ограждение, которое я хотел установить. Огромный успех!

Извините за касание к частному государству. Я просто думаю, что это одна из самых крутых вещей, которые делает возможным закрытие.

Вот последний пример закрытия в действии:

Здесь у нас есть функция высшего порядка (функция, которая работает с другими функциями), называемая moduloFactory. Это функция, которая возвращает другие функции, поэтому вы также можете назвать ее фабрикой функций (отсюда слово «фабрика» в названии).

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

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

Замыкания - это круто, правда? Они были там все время, их просто не замечали. Они не ищут внимания. Это настенные цветы. Вы должны найти их, прежде чем действительно почувствуете, кто они. Но, как и большинство интровертов, они стоят времени и усилий, чтобы познакомиться с ними.

Надеюсь, я хорошо представился. 😅

Эта статья является частью серии статей, посвященных концепциям легко усваиваемого кода для новичков в веб-разработке, которые ищут более эффективные подходы к решению проблем с кодом.