Что такое замыкание в программировании
medium

Что такое замыкание в программировании

Это когда вкладываешь одну функцию в другую

Сегодня разбираем полезное понятие из мира программирования — замыкание. Это нужно тем, кто хочет серьёзно заниматься разработкой и говорить со старшими товарищами на одном языке. 

Для начала потребуется два термина: область видимости и стек. Если нужно вспомнить, раскрывайте: 

Область видимости определяет, к каким переменным функция, команда или другая переменная может получить доступ, а к каким нет. Проще говоря, что каждая функция «видит» — видит ли она те переменные и объекты, которые созданы за её пределами? Видит ли она то, что вложено в функции, которые запускаются внутри неё?

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

Стек — это как список задач при выполнении программы. Сначала компьютер исполняет один код, внутри которого появляется какая-то функция — это как будто отдельная программа. Компьютер откладывает текущую программу, делает себе в стеке пометку «вернуться сюда, когда доделаю новую программу» и исполняет эту новую функцию. Исполнил — смотрит в стек, куда вернуться. Возвращается туда. 

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

Что такое замыкание

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

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

Звучит сложно, объясним на примерах.

Пример замыкания в коде

Сделаем функцию, которая вернёт нам фразу «Привет, …» вместе с именем, которое мы в него отправим. Но сделаем это через замыкание — чтобы посмотреть, как именно всё устроено.

Обратите внимание на две переменные в конце: mike и maxim. По сути, эти переменные — ссылки на вызов результата функции hello(), но с конкретным параметром. 

// внешняя функция
function hello(name) {
	// внутренняя функция-замыкание
	// возвращаем её как результат работы внешней
	return function() {
		// внутренняя функция выводит сообщение на экран
		console.log("Привет, " + name);
	}
}

// создаём новые переменные, используя замыкание
mike = hello("Миша");
maxim = hello("Максим")
// запускаем внутреннюю функцию с нашими параметрами, просто указав имена переменной
mike();
maxim();

Ещё один пример, посложнее

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

Для примера сделаем замыкание и заведём две переменные — каждая будет выдавать сообщение со своим началом фразы, а продолжение будем передавать им в виде параметра:

// внешняя функция, у которой есть свой параметры
function greeting(hi) {
	// внутренняя функция-замыкание, тоже со своим параметром
	// возвращаем её как результат работы внешней
	return function(name) {
		// внутренняя функция выводит сообщение на экран
		console.log(hi + ", " + name);
	}
}

// создаём новые переменные, используя замыкание
morning = greeting("Доброе утро");
thnx = greeting("Спасибо за комментарий")
// запускаем внутреннюю функцию с нашими параметрами, указав параметры вызова
morning("коллеги");
thnx("Павел");

Причём здесь область видимости

Из последнего примера видно, что объявление переменных происходит так:

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

Но как такое может быть, когда внутренняя функция использует переменную из области видимости внешней функции, которой уже нет? 

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

Зачем нужны замыкания

На замыканиях строится около половины алгоритмов в функциональном программировании. А ещё на них можно построить много разного:

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

Что дальше

Следующий шаг — попробовать замыкания в деле. Напишем небольшой код и проверим, как работают замыкания и для чего они могут пригодиться.

Художник:

Даня Берковский

Корректор:

Ирина Михеева

Вёрстка:

Кирилл Климентьев

Соцсети:

Алина Грызлова

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Вам может быть интересно
medium
[anycomment]
Exit mobile version