Замыкания
Сегодня речь пойдет о замыканиях в JavaScript. Для многих эта тема подсознательно воспринимается непонятной и от того сложной. Но, в действительности, в замыканиях нет ничего страшного и сложного.
Что же такое замыкание? Если говорить простыми словами, то это просто функция в функции. Вот и все. Да-да. Так вот просто. Это функция, которая находится внутри другой функции.
Начнем сразу же с примеров, т.к. на них будет разобраться намного проще.
function hi() { return function() { console.log('Привет'); } }
Такая вот незамысловатая конструкция: у нас имеется функция hi
, которая возвращает другую функцию.
Получается, что если вызвать функцию hi
, то может показаться, что ничего не произошло, так как в консоль не будет выведено слово Привет
:
hi(); // в консоль ничего не выведется
Так как функция hi возвращает новую функцию, то нам нужно ее вызвать, перед эти, для наглядности запишем ее в константу и вызовем ее:
const sayHi = hi(); sayHi(); // выведет в консоль слово "Привет"
Только после этой манипуляции мы сможем визуально увидеть результат.
Итак, первым шагом мы разобрались, что функция hi
в результате своего выполнения возвращает новую функцию. Но пока что совсем непонятно зачем это нужно.
Давай разбираться зачем это нужно.
В нашу функцию hi
добавим параметр(аргумент), в который будем записывать имя человека, а в функции, которая сейчас выводит нам слово Привет в консоль добавим это имя. В итоге получим такой код:
function hi(name) { return function() { console.log(`Привет, ${name}`); } }
Теперь заставим все это работать:
const sayHi = hi('Вася'); sayHi(); // выведет в консоль: Привет, Вася
Стоит заметить, что имя мы передавали только в функцию hi
, однако, та функция, которую возвращает функция hi
так же имеет доступ к этому имени и спокойно может его использовать. На самом деле это и есть замыкание. Возвращаемая функция замыкает в себе значение переменной name
.
Поправим немного код, для большего понимания:
const sayHiVasya = hi('Вася'); const sayHiPetya = hi('Петя'); sayHiVasya(); // выведет в консоль: Привет, Вася sayHiPetya(); // выведет в консоль: Привет, Петя
Как видишь, мы передаем имена только в нашу функцию hi
, и эти имена замыкаются в возвращаемых функциях.
Создание ссылок для соц. сетей
Может быть еще не совсем понятно, поэтому давай сделаем более близкий к практике пример использующий замыкания.
Давай сделаем с тобой некий генератор ссылок для социальных сетей.
function createSocLink(socialNetwork) { return function(nickname) { return `https://${socialNetwork}/${nickname}`; } }
Итак, сначала разберем все в этом генераторе, а потом разберемся как им пользоваться.
В функцию createSocLink
мы передаем параметр socialNetwork
, который должен представлять из себя ссылку на какую-либо социальную сеть, т.е. должен иметь вид, к примеру:
- vk.com
- instagram.com
- facebook.com
Эта функция возвращает нам другую функцию, которая тоже ждет параметра, который указывает на никнейм пользователя в указанной социальной сети. Т.е. когда мы будем вызывать ту функцию, которую нам вернет функция createSocLink мы должны будем передать в нее параметр с указанием никнейма. Как выглядит никнейм в социальных сетях, думаю у тебя вопросов не вызовет.
Итак, пробуем все это запустить.
Так как функция createSocLink
вернет нам новую функцию, то запишем ее в константу:
const createVkLink = createSocLink('vk.com');
Теперь в createVkLink
у нас лежит функция, которая умеет делать ссылки для социальной сети Вконтакте. Теперь вызовем эту функцию и не забудем передать в нее аргумент, который должен указывать на никнейм пользователя:
const createVkLink = createSocLink('vk.com'); console.log(createVkLink('durov')); // в консоль выведется: https://vk.com/durov
Как видишь, мы создали ссылку на страницу создателя Вконтакте Павла Дурова.
Теперь давай создадим ссылки с помощью генератора на другие соц. сети и ты увидишь, в чем прелесть замыканий:
const createVkLink = createSocLink('vk.com'); const createInstagramLink = createSocLink('instagram.com'); const createFacebookLink = createSocLink('facebook.com');
Мы получили 3 новых функции:
createVkLink
– создаем ссылки на страницы пользователей в Вконтакте;createInstagramLink
– создает ссылки на страницы пользователей в Instagram;createFacebookLink
– создает ссылки на страницы пользователей в Facebook.
Попробуем их в работе:
console.log(createVkLink('durov')); console.log(createVkLink('admin')); console.log(createVkLink('vasya')); console.log('*****'); console.log(createInstagramLink('durov')); console.log(createInstagramLink('admin')); console.log(createInstagramLink('vasya')); console.log('*****'); console.log(createFacebookLink('durov')); console.log(createFacebookLink('admin')); console.log(createFacebookLink('vasya'));
Получаем результат:
Ссылки прекрасно сгенерировались. Благодаря замыканию, мы получили список из 3ех генераторов ссылок:
const createVkLink = createSocLink('vk.com'); const createInstagramLink = createSocLink('instagram.com'); const createFacebookLink = createSocLink('facebook.com');
И каждый генератор теперь может генерировать сколько угодно ссылок, при этом, в него нужно передавать только никнейм пользователя, а сам адрес социальной сети будет браться из замыкания.
Домашнее задание
Создать функцию calc
используя замыкания, которую можно использовать так:
const plus = calc(10); plus(5); // должно вывести значение 15 plus(45); // должно вывести значение 55