Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Результат немного другой от ожидаемого (https://javascript.ru/forum/misc/11879-rezultat-nemnogo-drugojj-ot-ozhidaemogo.html)

TicTac 19.09.2010 00:31

Результат немного другой от ожидаемого
 
Есть такой пример, взят из хабры, тема про замыкания
function createCounter() {
   var numberOfCalls = 0;
   return function() {
      return ++numberOfCalls;
   }
}
var fn = createCounter();
fn(); //1
fn(); //2
document.write(fn()); //3

Так вот почему после очередного вызова функции не обнуляется переменная numberOfCalls, а наоборот инкрементится и в результате numberOfCalls = 3, вместо ожидаемого 1.

хотя если просто вызвать последовательно три раза функцию тогда получаю как раз то что и ожидаю 1, почему так происходит?

function createCounter() {
   var numberOfCalls = 0;
	  return function() {
      return ++numberOfCalls;
   }
}
createCounter(); //1
createCounter(); //2
document.write(createCounter()()); //3

Sweet 19.09.2010 01:16

Прям фиг знает, как объяснить:)
function createCounter() {
   var numberOfCalls = 0;
   return function() {
      return ++numberOfCalls;
   }
}
var fn = createCounter();
alert(fn);

Т.е. в первом случае fn - это функция, которая имеет в себе типа локальную переменную numberOfCalls, доступную внутри функции. И каждый вызов fn увеличивает ее значение на единицу и возвращает его. Поэтому после 3х вызовов функция возвращает 3.
А второй пример кривоват. Вызов createCounter() ничего не дает в первых двух случаях.
function createCounter() {
  var numberOfCalls = 0;
  return function() {
    return ++numberOfCalls;
  }
}
alert(createCounter());

Если же вызвать функцию, которую возвращает createCounter(), то она вернет один и благополучно умрет, так что многократный вызов createCounter()() не даст того же эффекта, что и многократный вызов fn().
Ну или тип того:)

TicTac 19.09.2010 01:42

Спасибо.

Да я понимаю что второй случай бесполезный три раза вызывать одну и туже функцию...

Только не совсем понимаю если с помощью fn() вызываем три раза функцию почему же ее значение накапливается, а не обнуляется как во вотором случае. Функция после fn() завершается возвращает 1. Все! Все локальные переменные функции по выходе из области видимости функции createCounter() должны быть удалены. Походу так и происходит при три кратном вызове одной и той же функции, которая во втором примере. Но тут так не происходит. Только почему? О_о

Более того если вставить document.write(numberOfCalls) еще в функцию то окажется что она выполниться все один раз по первому примеру. Вообще выходит странно как-то.
var numberOfCalls = 0;
document.write(numberOfCalls);

TicTac 19.09.2010 11:43

Вроде разобрался. :) только правильно ли я понял

function createCounter() {
   var numberOfCalls = 0;
   return function() {
      return ++numberOfCalls;
   }
}
var fn = createCounter();
fn(); //1
fn(); //2
document.write(fn()); //3


1. Всего 1 запуск функции createCounter(), fn = createCounter(); выполняется функция createCounter() возвращает переменной fn
function() {
      return ++numberOfCalls;
   }

2. scope createCounter() функции не удаляется так так как вложенной может понадобиться ее переменные

3. далее происходит вызов три раза
function() {
      return ++numberOfCalls;
   }

переменная numberOfCalls; в итоге 3

А во втором примере тот что писал в первом сообщении, после выполнения createCounter естественно все удаляется по завершению каждый раз.


Только теперь непонятно, когда будет удалена переменная numberOfCalls если следовать первому примеру, она так и повиснет в памяти навсегда?

Sweet 19.09.2010 12:20

Общий смысл ты понял, и это самое главное. Конечно, во втором пункте у тебя не совсем корректные выводы, но это не важно:)
Цитата:

Сообщение от TicTac
Только теперь непонятно, когда будет удалена переменная numberOfCalls если следовать первому примеру, она так и повиснет в памяти навсегда?

Да, висят. Но в этом и есть их смысл.

TicTac 19.09.2010 12:35

понятно, спасиб.

Sweet 19.09.2010 14:57

Цитата:

Сообщение от Sweet
во втором пункте у тебя не совсем корректные выводы, но это не важно

Хотя здесь я неправ.
Цитата:

Сообщение от TicTac
scope createCounter() функции не удаляется

numberOfCalls храниться в fn. Поэтому если нужно убрать эту ее, нужно просто очистить fn (например, fn = null)


Часовой пояс GMT +3, время: 16:40.