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

Так что же такое замыкание в JS?

Давайте посмотрим на этот пример:

function createFunc() {
    var msg = 'Hello World';
    function print() {    
         console.log(msg)    
    }
    return print;
}
var myFunc = createFunc();
myFunc();

Это дает нам следующий вывод в консоли:

Hello World

Так что же на самом деле происходит в коде?

Мы определили функцию с именем createFunc.

Внутри этой функции у нас есть переменная с именем msg (сообщение) и внутренняя функция, определенная как print, которая просто записывает в консоль содержимое msgпеременная.

function createFunc() {
    var msg = 'Hello World';
    function print() {    
        console.log(msg)    
    }
    return print;
}

Затем возвращается функция print.

return print;

Затем я определяю другую переменную с именем myFunc вне createFunc, значение которой получается в результате выполнения createFunc.

var myFunc = createFunc();

Поскольку createFunc, возвращает ссылку на функцию print, myFunc — это просто другое имя (псевдоним) для print.

После всего этого я, наконец, запускаю myFunc, который имеет ссылку на print.

myFunc();

Объяснение вывода:

Когда я, наконец, выполню myFunc, как показано ниже:

myFunc();

На самом деле я выполняю print, но вне определения createFunc. Вот в чем загвоздка: вне createFunc нет переменной msg, она была определена внутри createFunc. Итак, что регистрируется в консоли, т.е. содержимое msg???

Когда createFunc выполняется, как показано ниже,

var myFunc = createFunc();

он не просто возвращает ссылку на print, как я упоминал ранее, он возвращает лексическую область действия функции createFunc. Теперь, что означает лексическая область действия? Проще говоря, он состоит из всех переменных и функций, которые были определены внутри createFunc во время выполнения, в данном случае это означает переменную msg. Короче говоря, javascript хорошо возвращает msg.

Поэтому, когда я запускаю myFunc извне createFunc, вот так:

myFunc()

которая имеет ссылку на print и лексическую область видимости. Функция print имеет доступ к переменной msg и ее содержимое 'Hello World'. Поэтому мы получаем

Hello World

Это самый простой и наглядный пример замыкания.

Итак, в конечном счете, что такое закрытие?

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

Поворот :

Что, если бы я попытался запустить приведенный ниже код:

var msg = 'Hello World from outside'
function createFunc() {
    var msg = 'Hello World from inside';
    function print() {    
         console.log(msg)    
    }
    return print;
}
var myFunc = createFunc();
myFunc();

Теперь у меня есть 2 переменные с именами msg в моем коде. Одно msg определено вне createFunc, а другое — внутри createFunc.

Что происходит сейчас?

myFuncвсе еще имеет ссылку на print и лексическую область действия createFunc, поэтому, когда myFunc выполняется, консоль записывает

Hello World from inside

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

В этом примере объясняется как область действия, так и закрытие.

Давайте сделаем все кристально чистым

Что, если бы у меня был этот код со мной:

var msg = 'Hello World from outside'
function createFunc() {
    var msg = 'Hello World from inside';
    function print() {    
       
          var msg = 'Hello World from print';
          console.log(msg)  
  
    }
    return print;
}
var myFunc = createFunc();
myFunc();

Все, что мы обсуждали ранее, происходит и выше: ссылка на print возвращается вместе с лексической областью createFunc, только на этот раз Функция печати имеет переменную с именем msg, определенную внутри себя. Итак, на этот раз мы получаем вход в консоль

Hello World from print

Почему это так? Как вы могли догадаться, функция myFunc, которая является ссылкой на print, имеет в своей собственной области действия переменную msg уже определено ("Hello world from print"). Это сообщение, определенное внутри print, перезаписывает все остальные сообщения. Это концепция предпочтения области действия, т. е. предпочтение перемещается изнутри функции во внешнюю функцию и полностью в глобальную область.

Спасибо за чтение. Пожалуйста, не забудьте оставить какие-либо комментарии, если они у вас есть, и ознакомьтесь с моей следующей статьей о замыканиях: https://medium.com/@parvezdittia/javascript-closures-made-simple-part-2-private-variables-functions- а14536а99бе2