Как работает код счётчика, в котором одна функция возвращает другую функцию? [дубликат]

133
25 июля 2019, 20:40

На данный вопрос уже ответили:

  • Как работают замыкания в JavaScript 7 ответов

function makeCounter() { 
  var currentCount = 1; 
 
  // возвращаемся к функции 
  return function counter() { 
    return currentCount++; 
  } 
}; 
var d = makeCounter()

В внутри функции makeCounter мы создаем функция counter в которой увеличиваем значение currentCount на 1 т.к так переменная currentCount не объявлена она ищет ее с помощью скрытого свойства [[scope]] которое есть у функции; переменная currentCount = 1; ее и увеличивает функция counter т.к. внутри функции переменная currentCount++ с постинкрементом то значение увеличивается но возвращается старое значение. переменная d = 1; а что происходит в этом коде ?

function makeCounter() { 
  var currentCount = 1; 
 
  // возвращаемся к функции 
  function counter() { 
    return currentCount++; 
  } 
 
  // ...и добавляем ей методы! 
  counter.set = function(value) { 
    currentCount = value; 
  }; 
 
  counter.reset = function() { 
    currentCount = 1; 
  }; 
 
  return counter; 
} 
 
var counter = makeCounter();

тут возвращается не функция а что ? не могу понять

Answer 1

Функция makeCounter - это конструктор счётчика. Вызывая ее будет возвращен новый объект счетчика. Здесь это видно

function makeCounter() {
    ...
    return counter;
}
var counter = makeCounter();

Сам возвращаемый counter, если посмотреть чуть выше, является функцией

function counter() {
    return currentCount++;
}

Иными словами, вызывая makeCounter() (создать счетчик) мы просто получаем на выходе другую функцию - counter (которая уже является самим счетчиком). Эту функцию теперь можно вызывать и при этом благодаря такой замечательной штуке как "замыкания" будет возвращена и инкрементирована локальная (локальная для makeCounter) переменная currentCount, содержащая текущее значение счетчика. Вызываем counter 1 раз - выход 1. Вызываем десять подряд - последним значением получим 10. Ничего сложного здесь

function makeCounter() { 
  var currentCount = 1; 
 
  function counter() { 
    return currentCount++; 
  } 
 
  return counter; 
} 
 
var counter = makeCounter(); 
console.log(counter()); 
counter() 
counter() 
counter() 
counter() 
counter() 
counter() 
counter() 
counter() 
console.log(counter());

Интереснее с вот этой частью

  counter.set = function(value) {
    currentCount = value;
  };
  counter.reset = function() {
    currentCount = 1;
  };

На самом деле ничего сложного здесь тоже нет. Стоит помнить что в JavaScript практически все является объектом. Функции в том числе. Поэтому равно как вы можете добавлять свойства объекту (var o = {}; o.a = 1; o.b = 2;), точно так же вы можете добавлять свойства и функции. Так почему бы не добавить нашему счетчику возможность начинать счет с чего-нибудь кроме единицы? Или сбрасываться в начальное состояние?

Так и сделано. Добавлены свойства (точнее сказать методы) объекту counter (да-да, именно объекту, ведь какая разница, что это функция?) с названиями set и reset, которые, соответственно, устанавливают счетчик в какое-нибудь значение, указанное Вами, или обнуляют (точнее "объединичивают") счетчик

function makeCounter() { 
  var currentCount = 1; 
 
  function counter() { 
    return currentCount++; 
  } 
 
  counter.set = function(value) { 
    currentCount = value; 
  }; 
 
  counter.reset = function() { 
    currentCount = 1; 
  }; 
 
  return counter; 
} 
 
var counter = makeCounter(); 
counter(); // 1 
counter(); // 2 
counter(); // 3 
 
counter.reset(); // обнуляем, снова будет 1 
 
counter(); // 1 
counter(); // 2 
counter(); // 3 
 
counter.set(10); // а теперь возьмем и установим счетчик в 10 
 
counter(); // 10 
counter(); // 11 
counter(); // 12 
 
// Проверяем? 
console.log(counter()); // должно быть 13

READ ALSO
парсер cookie по url

парсер cookie по url

Имеется url необходимо парсить cookie на javascrip или на jquery, как это можно сделать:

134
Yandex map API как изменить картинку у ballon через json

Yandex map API как изменить картинку у ballon через json

Ребят как у ballon изменить картинку именно через json

155
Ребят по стеку вызовов подскажите (setTimout) js

Ребят по стеку вызовов подскажите (setTimout) js

Проблема в том, что после того как курсор покинул блок срабатывает clear, но запущенные таймеры (которые уже в стеке) не отменяются, как с таким...

115
Двумерный массив Js

Двумерный массив Js

Матрица М состоит из 6 строк, 8 столбцовВыяснить, сколько элементов в каждой строке превышают среднее арифметическое значение, определенное...

128