Выбрать главу

  var counter =0; // Частное значение для функции ниже

  return function() { return counter++; };

}());

Внимательно изучите этот пример, чтобы понять, как он действует. На первый взгляд, первая строка выглядит как инструкция присваивания функции переменной uniquelnteger. Фактически же это определение и вызов функции (как подсказывает открывающая круглая скобка в первой строке), поэтому в действительности переменной uniquelnteger присваивается значение, возвращаемое функцией. Если теперь обратить внимание на тело функции, можно увидеть, что она возвращает другую функцию. Именно этот объект вложенной функции и присваивается переменной uniquelnteger. Вложенная функция имеет доступ к переменным в ее области видимости и может использовать переменную counter, объявленную во внешней функции. После возврата из внешней функции никакой другой программный код не будет иметь доступа к переменной counter: вложенная функция будет обладать исключительным правом доступа к ней.

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

function counter() { var n = 0;

  return {

    count: function() { return n++; },

    reset: function() { n = 0; }

  };

}

var c = counter(), d = counter(); // Создать два счетчика

c.count()         // => 0

d.count()         // => 0: они действуют независимо

с.reset() // методы reset() и count() совместно

// используют одну переменную

c.count() // => 0: сброс счетчика с

d.count() // => 1: не оказывает влияния на счетчик d

Функция counter() возвращает объект «счетчика». Этот объект имеет два метода: count(), возвращающий следующее целое число, и reset(), сбрасывающий счетчик в начальное состояние. В первую очередь следует запомнить, что два метода совместно используют одну и ту же частную переменную n. Во-вторых, каждый вызов функции counter() создает новую цепочку областей видимости и новую скрытую переменную. То есть, если вызвать функцию counter() дважды, она вернет два объекта-счетчика с различными скрытыми переменными. Вызов методов count() и reset() одного объекта-счетчика не оказывает влияния на другой.

Важно отметить, что описанный прием образования замыканий можно использовать в комбинации с приемом определения свойств с методами доступа. Следующая версия функции counter() является вариацией примера, представленного в разделе 6.6, но здесь для хранения скрытой информации вместо обычного свойства объекта используются замыкания:

function counter(n) { // Аргумент n функции - скрытая переменная

  return {

    // Метод чтения свойства возвращает и увеличивает переменную счетчика,

    get count() { return n++; },

    // Метод записи в свойство не позволяет уменьшать значение n

    set count(m) {

      if (m >= n)

        n = m;

      else throw Error( "значение счетчика нельзя уменьшить");

    }

  };

}

var с = counter(1000);