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

Хорошо, давайте сначала посмотрим, что наш дружелюбный надежный источник всего Js (MDN) говорит о замыканиях.

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

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

function outer(){
  function inner(){
    }
}

Теперь вы можете подумать, что когда у нас будет такой сценарий? Давайте рассмотрим непрактичный, но простой пример, а затем перейдем к более подробному: 3

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

Итак, это непрактичный и глупый пример, нам не нужно делать это, чтобы утешить то, но что, если бы у нас было больше функций, больше, чем одна? Скажем...

Итак, только что произошло что-то интересное, что-то очень важное, а именно две функции теперь совместно используют переменную имени, потому что они обе имеют доступ к внешней области видимости, что делает замыкания особенными. Представьте, что у вас есть десятки функций в реальном приложении, где им нужен доступ к десяткам вещей, к которым им нужен доступ. Отлично! замыкание спасает от повторений и даже лучше, а если бы имя было динамическим??

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

const name =tyagi; 
function talk(){
        console.log(`Hi! my name is ${name}`)
    }
    function feel(){
    console.log(`${name} is feeling goooddd.. as we should!`)
    }
    talk();
    feel();

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

function me(name){
    function talk(){
        console.log(`Hi! my name is ${name}`)
    }
    function feel(){
    console.log(`${name} is feeling goooddd.. as we should!`)
    }
    talk()
}

Один из способов сделать это — создать объект и сделать эти функции методами этого объекта, а затем мы можем вызывать эти методы, когда захотим.

Итак, теперь эта функция me становится фабричной функцией, которая создает объект и отправляет его вам, чтобы вы могли назначить его переменным и прочему.
Другой , интересная вещь, которая только что произошла, заключается в том, что если мы вернемся к первоначальной функции me, которую мы создали, функции feel или talk имели доступ к переменной имени, когда они искали имя, они могли просто найти его, но теперь что функция me возвращает объект, что означает, что внутренняя функция не может быть вызвана до тех пор, пока мы ее не вызовем, функция me может быть уже выполнена и завершена.
Это означает, что внутренние функции каким-то образом удерживаются значение этого имени переменной, потому что, когда мы говорим dude.talk(), мы больше не выполняем меня, и эта функция разговора удерживает значение имени, даже если оно больше не существует. В этом и заключается волшебство: найти значение или сохранить его для будущего использования.

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

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

Допустим, у нас есть три кнопки на нашем веб-сайте, и каждая кнопка изменяет размер шрифта контента.

document.getElementById("size-12").onclick=function(){
    document.body.style.fontSize='12px'
} 
document.getElementById("size-14").onclick=function(){
    document.body.style.fontSize='14px'
}
document.getElementById("size-16").onclick=function(){
    document.body.style.fontSize='16px'
}

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

function clickHandler(size){
    document.body.style.fontSize=`${size}px`
}

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

document.getElementById("size-12").onclick=clickHandler(12px)
document.getElementById("size-14").onclick=clickHandler(14px)
document.getElementById("size-16").onclick=clickHandler(16px)

Но видите ли вы, почему это не сработает?
Потому что на самом деле мы не назначаем функцию onclick, мы назначаем возвращаемое значение, потому что мы вызываем его, и что JS делает, так это то, что когда мы вызываем функция, она переходит к ней и делает то, что нужно, и возвращает, и присваивает onclick той вещи, которая в данном случае не определена, потому что при назначении функции мы не должны ее вызывать, и если я не вызываю ее, как я Я собираюсь передать значение? и если я хочу вызвать его и передать значение, оно должно вернуть что-то отличное от неопределенного, и если вы угадали функцию, то вы правы!
Итак, давайте перепишем наш обработчик кликов

function clickHandler(size){
    retrun function(){document.body.style.fontSize=`${size}px`
      }
}

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

document.getElementById("size-12").onclick=clickHandler(12px)
document.getElementById("size-14").onclick=clickHandler(14px)
document.getElementById("size-16").onclick=clickHandler(16px)

и это значение прямо здесь, например, если мы скажем, что 12 будет храниться внутри этой внутренней функции в качестве ссылки внутри функции, которая его вернет, и именно поэтому замыкания ценны.
Одно из важных и практичных мест, где вы можете использовать Замыкания, находится внутри HOFФункций высшего порядка. Несмотря на то, что это одна строка, если бы это было реальное приложение, Closures может спасти вас от большого количества повторений, написав ее один раз.