class DarkRaha extends com { // разработка приложений
            String a="Главная" b="Контакты" c="О сайте"
};

JavaScript

Основы

Введение
Внедрение
Комментарий
Утверждения
Идентификаторы
Типы данных
Литералы
Переменные
Область видимости
Строки
Массивы
Ассоциативные массивы
Выражения и операции
Управляющие операторы
Функции
ООП - объекты
ООП - прототип, наследование
Замыкание
RTTI
Исключения
Объект Math
Объект Global
Объект Number
Регулярные выражения
XML DOM

библиотеки

Справочник по JavaScript

Замыкание (closure)

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

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


// пример вычисления производный из википедии
// здесь возвращаемая функция связывается с 
// аргументами внешней функции
function derivative(f, dx) {
  return function(x) {
    return (f(x + dx) - f(x)) / dx;
  };
}

Как это работает? В большинстве языков локальные переменные и аргументы переданные копированием создаются при вызове функции и существуют, пока функция выполняется. Концепция замыкания вносит в это правило исключение. Это случай, когда внешняя функция возвращает в качестве значения вложенную функцию, которая имеет хотя бы одну ссылку на свое окружение. Сборщик мусора JavaScript не может уничтожить локальный объект внешней функции и сохраняет его. При повторном вызове создается другой локальный объект, объекты предыдущих вызовов никак не затрагиваются. Таким образом, единственный кто имеет доступ к таким локально созданным объектам это конкретный экземпляр вложенной функции.

применение замыкания

Ниже приведен пример создания объекта с приватными членами.


var obj = function() { // определяем внешнюю функцию

   // так сказать приватные члены
   var myvar = "Hello World";
   var mymethod = function() {
       alert("Hello World");
   }
    
   return { // возвращаем массив вложенных функций
            // использующих замыкание
       "useMyvar" : function () {
          document.write(myvar+"<br>");
       },
       
       "setMyvar" : function(arg) {
           myvar = arg;
       },
       
       "useMymethod" : function() {
           mymethod();
         }       
      }
   }
    (); // сразу вызываем нашу внешнюю функцию


obj.useMyvar();
obj.setMyvar("other string");
obj.useMyvar();
// obj.useMymethod();
Результат:

возможные проблемы

Замыкания весьма способствуют созданию круговых ссылок, т.е. когда объекты ссылаются друг на друга. Когда же подобные ссылки включают DOM объекты или ActiveX в IE это приводит к утечке памяти. Объекты находятся в памяти до тех пор, пока запущен IE.

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


/* в этом случае все сгенерированные функции
используют одну и ту же переменную, чье значение 
после окончания цикла будет равно els.length. 
В результате при клике на этих элементах будет 
сообщение со значением els.length, а не 0,1,2...
*/ 
for (var i=0; i<els.length; i++) {
  els[i].onclick = function() { 
     // как-то используем i
     alert(i);  
   }
}

// в данном случае при клике на элементе 
// будет выведено сообщение с номером, под которым 
// элемент был в массиве els
for (var i=0; i<els.length; i++) {
   // вводим доп. функцию, где счетчик передается как аргумент
   (function(arg) { 
      els[arg].onclick = function() {
         alert(arg);
      }
   })(i);// вызываем внешнюю функцию в цикле
}

Рейтинг@Mail.ru