Давайте лучше поймем, что такое замыкание.

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

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

Я собираюсь поговорить о том, что такое закрытие. Я люблю объяснять простым языком.

Итак, что такое закрытие?

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

Прежде чем мы перейдем к заключению, я хотел бы кратко объяснить область.

Рассмотрим этот пример.

{
    let myName = 'Jinsung';
}

console.log(myName);    // ReferenceError: myName is not defined

`{ }` образует блок (они кажутся знакомыми, потому что у каждой функции есть свой блок!) и каждый блок имеет свою область действия.

В этом блоке определена переменная myName, и когда я печатаю переменную myName, она показывает ошибку.

Это происходит потому, что любые переменные или функции, созданные в блоке, доступны ТОЛЬКО в этом блоке.

Тогда как насчет этого примера?

{
    let myName = 'Jinsung';

    console.log(myName);    // prints 'Jinsung'
}

Теперь этот код работает,

потому что console.log() находится внутри того же блока, где был определен myName, и он может получить доступ к myName.

Эти две строки кода находятся в одной области.

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

let fruits = {'apple':10, 'orange':5};

function eatOneApple(){

    fruits['apple'] -= 1;
}

eatOneApple();

console.log(fruits); // {'apple':9, 'orange':5}

Переменная fruits определена в глобальной области.

Когда переменная определена в простом файле javascript (она не находится внутри какого-либо блока), она называется глобальной переменной, а глобальная переменная имеет глобальную область действия.

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

И функция eatOneApple() имеет `{ }`(блок), и этот блок имеет область видимости функции или локальную область видимости.

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

Вот когда происходит закрытие.

let fruits = {'apple':10, 'orange':5};

function eatOneApple(){

    fruits['apple'] -= 1;
}

eatOneApple();

console.log(fruits); // {'apple':9, 'orange':5}

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

eatOneApple() может получить доступ к объекту fruits и изменить объект fruits, который остается даже после завершения выполнения функции.

Переменная fruits изменена навсегда, потому что eatOneApple() изменила fruits из своей области действия.

Вернемся к определению, которое мы видели ранее,

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

Надеюсь, это поможет вам лучше понять это.

Теперь давайте перейдем к тому, почему люди говорят о закрытии.

Очень часто люди часто говорят о закрытии в этом конкретном контексте.

Рассмотрим этот пример.

function prepareToTalk(myName){
    
    let introduce = function(toWhom){

    console.log(`hello ${toWhom}, my name is ${myName}`);
    }
    
    return introduce;
}

Что здесь происходит?

Я создал функцию prepareToTalk(), которая принимает строковую переменную myName,

и внутри функции я создал еще одну функциональную переменную с именем introduce.

А prepareToTalk()возвращает ссылку на функцию introduce.

Хорошо, так как это закрытие?

Мы знаем, что myName передается в качестве аргумента внешней функции prepareToTalk.

Это означает, что myName находится внутри внешней области видимости функции prepareToTalk,

но анонимная функция (function(toWhom)) назначается переменной introduce, как в примере ниже.

let introduce = function(toWhom){

    console.log(`hello ${toWhom}, my name is ${myName}`);
}

Переменная introduce имеет собственную область внутренней функции, а в области внутренней функции она использует переменные toWhom и myName.

Переменная myName НЕ находится во внутренней функции, а находится во внешней функции prepareToTalk(),

но доступ к myName осуществляется во внутренней области функций, которая есть у introduce.

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

Как и когда использовать замыкание?

Продолжая приведенный выше пример,

function prepareToTalk(myName){
    let introduce = function(toWhom){
    
    console.log(`hello ${toWhom}, my name is ${myName}`);
}
    return introduce;
}

let jinsung = prepareToTalk('Jinsung');

console.log(jinsung);      // ??

Что произойдет, если мы вызовем prepareToTalk() и назначим его переменной jinsung?

[Function: introduce]

Переменная jinsung возвращает объект функции с именем introduce .

Это похоже на следующий пример.

function print(name) {
    console.log(name);
    return name;
}

const printName = print;

console.log(printName); // [Function: print]

Переменная printName имеет значение ссылки на функциональный объект print.

Это все, что он делает. Он НЕ вызывает функцию print.

Чтобы вызвать print, мы ставим «()» рядом с printName.

Так же, как пример ниже.

function print(name) {
    console.log(name);
}


const printName = print;

printName('JSK'); // prints 'JSK'

Возвращаясь к исходному примеру,

function prepareToTalk(myName){

    let introduce = function(toWhom){
    
    console.log(`hello ${toWhom}, my name is ${myName}`);
}

    return introduce;
}

let nabi = prepareToTalk('Nabi');    // [Function: introduce]
const nabiToJinsung = nabi('Jinsung');

nabiToJinsung; // prints 'hello Jinsung, my name is Nabi'

В этой строке кода

const nabi = prepareToTalk('Nabi');

Строка «Наби» передается в качестве аргумента в функцию prepareToTalk() и присваивается переменной myName.

переменная myName находится во внешней функции prepareToTalk() ,

и доступен во внутренней функциональной переменной introduce в любое время.

(определение замыкания)

Когда мы звоним prepareToTalk(‘Nabi’),

он НЕ возвращает какое-либо вычисленное значение или что-то еще, он возвращает только ссылку на объект функции с именем introduce.

Возвращаемое значение: [Function: introduce]

Поскольку prepareToTalk() возвращает ссылку на функцию introduce, переменная nabi также возвращает ссылку на функцию introduce.

Чтобы вызвать introduce, мы можем поставить `( )` рядом с nabi.

nabi('Jinsung');  

// calling introduce() function with 'Jinsung' string argument.

И чтобы присвоить это значение переменной, мы можем написать

const nabiToJinsung = nabi('Jinsung');

// prints 'hello Jinsung, my name is Nabi'

Мы также можем попробовать создать разные объекты с одним и тем же строковым значением «Наби», назначенным myName.

function prepareToTalk(myName){

    let introduce = function(toWhom){
    
    console.log(`hello ${toWhom}, my name is ${myName}`);
}

    return introduce;
}

let nabi = prepareToTalk('Nabi');    // [Function: introduce]

const nabiToJinsung = nabi('Jinsung'); // // prints 'hello Jinsung, my name is Nabi'
const nabiToHarry = nabi('Harry'); // prints 'hello Harry, my name is Nabi'
const nabiToJacob = nabi('Jacob'); // prints 'hello Jacob, my name is Nabi'
const nabiToLee = nabi('Lee'); // prints 'hello Lee, my name is Nabi'

Переменные nabiToHarry, nabiToJacob и nabiToLee совместно используют одну и ту же внешнюю переменную myName в своей внешней функции prepareToTalk().

Изменение переменной myName изменит значение всех связанных с ней переменных.

function prepareToTalk(myName){

    let introduce = function(toWhom){
    
    console.log(`hello ${toWhom}, my name is ${myName}`);
}

    return introduce;
}

let nabi = prepareToTalk('🐱MEOW🐱');    // changed from 'Nabi' to '🐱MEOW🐱'

const nabiToJinsung = nabi('Jinsung'); // // prints 'hello Jinsung, my name is 🐱MEOW🐱'
const nabiToHarry = nabi('Harry'); // prints 'hello Harry, my name is 🐱MEOW🐱'
const nabiToJacob = nabi('Jacob'); // prints 'hello Jacob, my name is 🐱MEOW🐱'
const nabiToLee = nabi('Lee'); // prints 'hello Lee, my name is 🐱MEOW🐱'

Надеюсь, теперь вы понимаете, что такое замыкание лучше.

Если ты этого не понял,

напишите мне на [email protected]

или напишите мне на linkedin.

Я вернусь к вам, как только смогу.