вернуться к уроку

Кеширующий декоратор

важность: 5

Создайте декоратор makeCaching(f), который берет функцию f и возвращает обёртку, которая кеширует её результаты.

В этой задаче функция f имеет только один аргумент, и он является числом.

  1. При первом вызове обёртки с определённым значением аргумента – она вызывает f и запоминает её результат.
  2. При втором и последующих вызовах с тем же значением аргумента – возвращается сохранённое значение результата.

Должно работать так:

function f(x) {
  return Math.random() * x; // random для удобства тестирования
}

function makeCaching(f) { /* ваш код */ }

f = makeCaching(f);

var a, b;

a = f(1);
b = f(1);
alert( a == b ); // true (значение закешировано)

b = f(2);
alert( a == b ); // false, другой аргумент => другое значение

Открыть песочницу с тестами для задачи.

Запоминать результаты вызова функции будем в замыкании, в объекте cache: { ключ:значение }.

function f(x) {
  return Math.random()*x;
}

function makeCaching(f) {
  var cache = {};

  return function(x) {
    if (!(x in cache)) {
      cache[x] = f.call(this, x);
    }
    return cache[x];
  };

}

f = makeCaching(f);

var a = f(1);
var b = f(1);
alert( a == b ); // true (значение закешировано)

b = f(2);
alert( a == b ); // false, другой аргумент => другое значение

Обратите внимание: проверка на наличие уже подсчитанного значения выглядит так: if (x in cache). Менее универсально можно проверить так: if (cache[x]), это если мы точно знаем, что cache[x] никогда не будет false, 0 и т.п.

function makeCaching(f) {
  var cache = {};

  return function(x) {
    if (!(x in cache)) {
      cache[x] = f.call(this, x);
    }
    return cache[x];
  };

}

Открыть решение с тестами в песочнице.