Замыкания в JavaScript: базовое руководство

Автор оригинала: Parathan Thiyagalingam
  • Перевод
Представляем вашему вниманию перевод статьи Parathan Thiyagalingam, опубликованной на сайте medium.freecodecamp.org. Хотите узнать, как работают замыкания в JavaScript? Загляните под кат!


Фото Austin Distel с Unsplash

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

Перед тем как начать разбираться с понятием замыканий, рассмотрим, что такое цепочки областей видимости в JavaScript.

Как правило, выделяют два типа областей видимости: глобальные и локальные.

В JavaScript переменная внутри функции не доступна снаружи — в отличии, например, от переменных внутри блока (в условиях вроде if и while).

Исходя из этого, у функции в JavaScript есть область видимости, а у блока — нет.

var a = 10;
function app(){
   var b = 2;
   console.log(a); // 10
   console.log(b); // 2
}
console.log(b); //   ReferenceError: b is not defined
app();

Как мы уже знаем, a — глобальная переменная, а b — локальная, то есть используемая только функцией app. Вне локальной области видимости у нас нет доступа к локальной переменной.

Как использовать вложенную функцию (функцию внутри функции)


var a = 10;
function app(){
     var b = 2;
     var d = 3;
  function add(){
     var c = a + b;
   }
 return add;
}
var x = app();
console.dir(x);

На примере выше app — это родительская функция, add — дочерняя.

  • Для отображения всех свойств выбранного объекта вместо console.log используется console.dir.
  • Переменная х присваивается функции app, которая далее возвращает функцию add. Это позволяет увидеть все свойства объекта функции add.

Если вы откроете консоль в браузере, то обнаружите объект Closure внутри массива данных Scopes.



Поскольку внутренняя функция add имеет доступ к переменным b и d, которые принадлежат внешней функции, эти две переменные будут добавлены в объект Closure в качестве ссылки.
Рассмотрим еще один пример замыкания.

var a = 10;
var startFunc;
function app(){
      var b = 2;
   function add(){
      var c = a + b;
      console.log(c);
   }
   startFunc = add();
}
app(); // Invoke the app function
startFunc; 
// as the app function invoked above will assign the add function to startFunc & console the value of c

  • Глобальной функции startFunc присваивается функция add, которая является дочерней для родительской функции app.
  • Это становится возможным только после вызова функции app. В противном случае функция startFunc будет вести себя как глобальная переменная без присвоенного значения.

Как использовать замыкания в JavaScript


Многие из нас, используя замыкания при написании кода, не до конца понимают, почему это делают. В JavaScript отсутствуют модификаторы public, protected и private, которые есть в языках объектно-ориентированного программирования. Поэтому, чтобы закрыть доступ к пространству имен для внешнего кода, мы вынуждены прибегать к помощи функций.

И раз уж речь зашла о функциях — немедленно вызываемая функция (IIFE) запускается сразу после объявления. Ее даже не нужно вызывать.

Синтаксис IIFE выглядит так:

(function(){
             //variables & scope that inside the function 
})();

Рассмотрим такой пример:

var studnetEnrollment = (function () {
    //private variables which no one can change
    //except the function declared below.
     var count = 0;
     var prefix = "S";
    // returning a named function expression
     function innerFunc() {
         count = count + 1;
         return prefix + count;
     };
 return innerFunc;
})();
var x = studnetEnrollment(); // S1
console.log(x);
var y = studnetEnrollment(); // S2 
console.log(y);

count и prefix — две приватные переменные, которые невозможно изменить. Доступ к ним открыт лишь для внутренней функции (в нашем случае это функция innerFunc).

  • При первом вызове функции studentEnrollment функция innerFunc увеличивает значение переменной count до 1.
  • Во второй раз значение count увеличивается с 1 до 2.
  • Все это возможно только благодаря замыканию.

Заключение


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

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



Приятного кодинга!
Plarium
126,66
Разработчик мобильных и браузерных игр
Поделиться публикацией

Комментарии 3

    +3

    Я уже 10 лет знаком с JS. И кажется уже все написали по статье про замыкания. Неисчерпаемая тема (нет).

      +2
      Я вот тоже в этой сфере, но ещё не дорос до написания своей статьи по замыканиям. Придётся поднимать уровень!
      0
      Особенно познавательно тема замыканий смотрится с диаграммами ссылок на область памяти, какая переменная откуда доступна.

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое