Давайте лучше поймем, что такое замыкание.
Концепция закрытия была для меня сложной, но я думаю, что у меня был ага-момент для закрытия, и я хочу поделиться им здесь.
Моя цель – дать вам понять, что такое закрытие, к концу этой статьи.
Я собираюсь поговорить о том, что такое закрытие. Я люблю объяснять простым языком.
Итак, что такое закрытие?
Замыкание — это (явление), когда блок кода может получить доступ к объекту, находящемуся за пределами блока.

Прежде чем мы перейдем к заключению, я хотел бы кратко объяснить область.
Рассмотрим этот пример.
{
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.
Я вернусь к вам, как только смогу.