Замыкания

javascript, 04.12.2011 Воскресенье, 17:47
Теги: Суть, javascript, замыкание
wtf is {closure}?

Есть такой страшный термин как «замыкание» (closure). В истории наращивания моего опыта было три стадии моего осознования этого приема. Первая стадия заключалась в том что я не представлял значение и смысл применения замыканий (речь идет о javascript). Вторая стадия заключалась в том, что я понял принцип но не использовал замыкания в своих скриптах, так как не видел им применения. Третья стадия обуславливалась постоянным применением замыканий и получением кайфа от их удобства. В этой статье я постараюсь сразу показать вам их смысл и полезность.

В javascript есть такой термин как область видимости. Образно говоря область видимости переменной это пространство в котором к этой переменной можно обратиться напрямую. Традиционно разделяют два вида областей видимости, это глобальная область видимости и локальные области видимости (на самом деле это одно и то же, только на разных уровнях). Глобальная область видимости доступна нам изначально и реализуется объектом window. Локальные области видимости появляются когда мы создаем функции. Так вот, когда вы создаете функцию, то в её теле вы имеете доступ как к локальной области видимости самой функции так и к областям видимости стоящим выше (к той, в которой определена наша функция и дальше к глобальной области). Такая модель работы кода, когда функция представляет собой комбинацию программного кода и цепочки областей видимости, в которой этот код исполняется, в программировании и называется замыканием. Так что технически любая функция в javascript — это замыкание. Другое дело что традиционно замыканиями называют лишь некоторые случаи их применения. Создать сайт самому бесплатно это ни коим образом не мешает.

Есть ещё одна вещь, которая важна для понимания замыканий. Называется она garbage collector или сборщик мусора. Это технология которая позволяет интерпретатору javascript очищать память от уже использованных данных и не допускать переполнения памяти. Выглядит это примеро так:

Code
<script>
function outer(i){
  function inner(){++i;}
  inner();
  return i;
  }
   
alert(outer(1)); // 2
</script>

Сначала мы объявили функцию outer в глобальной области видимости, затем вызвали её. Когда она начала свою работу была объявлена вложенная функция inner, которая сразу и была запущена. Затем функция outer вернула результат и завершила работу. Как только это произошло, в дело вступил сборщик кода. Он определил что функция inner более недоступна для вызова, а значит может быть удалена. А теперь посмотрите на этот пример:

Code
<script>
function outer(i){
  return function inner(){return ++i;}
  }
outer = outer(1);
   
alert(outer()); // 2
alert(outer()); // 3
alert(outer()); // 4
</script>

Внимательно разберем код выше. Сначала мы объявили функцию outer, которая возвращает вложенную функцию inner в качестве результата своей работы. Далее мы переписали значение переменной outer и вместо самой функции outer поместили в переменную результат её вызова. По аналогии с предыдущим примером функция outer должна была быть удалена сборщиком мусора так как к ней, кажется, больше нет доступа, но на самом деле это не так. Мы действительно не можем больше вызвать первоначальную outer, так как она перезаписана, но, как показывают последующие три алерта, функция не была удалена и переменная i по прежнему существует. Произошло это потому, что на первоначальную функцию outer по прежнему осталась ссылка. Она существует в цепочке областей видимости результата работы первоначальной функции outer. Таким образом у нас получилось создать функцию, которая считает собственные вызовы. Такие конструкции обычно и называют явными замыканиями. Пример выше так же иллюстрирует ещё одно важное свойство замыканий — инкапсуляцию данных. Обратите внимание, после того как мы переписали первичную функцию outer, мы теряем возможность изменить каким либо образом (кроме предусмотренного самой функцией) переменную i. Это и есть инкапсуляция, проще говоря возможность взаимодействовать с внутренними свойствами объекта исключительно посредством специально предусмотренных интерфейсов.

Инкапсуляция данных посредством замыкания используется в моей галерее iLoad. Галерея имеет множество частных свойств и переменных, которые продолжают существовать всё время использования галереи но недоступны извне.

Таким образом можно объяснить смысл самого термина. Функция «замыкает» на себе вышестоящие области видимости и не дает им быть удаленными если к ним теряется доступ, а основное применение замыканий в программировании — хранение данных между вызовами функций и инкапсуляция данных.

Хорошая ссылка по теме: Замыкания на Javascript Garden


Жми на пятую!
42, 5440
    © Блог StudioAD.ru 2023 год нашей эры. Не все права защищены... Копирование любой информации и материалов с обратной ссылкой приветствуется! Хостинг от uCoz.

    Если вам пришлись по душе материалы моего блога - подпишитесь на RSS дабы получать обновления незамедлительно! Я рад что вы читаете и комментируете мои экзерсисы, приятного времяпрепровождения.