Автор оригинала: Divyanshu Maithani.
Функции являются неотъемлемой частью программирования. Они помогают добавить Модульность и Воспроизведение в наш код.
Вполне распространено разделить нашу программу в куски, используя функции, которые мы можем позвонить позже, чтобы выполнить некоторые полезные действия.
Иногда функция может стать дорогой, чтобы вызвать несколько раз (скажем, функцию для расчета факториала номер). Но есть способ, которым мы можем оптимизировать такие функции и сделать их намного быстрее: кэширование Отказ
Например, скажем, у нас есть Функция Чтобы вернуть факториал ряд:
function factorial(n) {
// Calculations: n * (n-1) * (n-2) * ... (2) * (1)
return factorial
}Отлично, теперь давайте найдем факториал (50) Отказ Компьютер выполнит расчеты и вернет нам окончательный ответ, сладкий!
Когда это сделано, давайте найдем факториал (51) Отказ Компьютер снова выполняет ряд расчетов и получает нам результат, но вы, возможно, заметили, что мы уже повторяем количество шагов, которые могли быть удалены. Оптимизированный способ будет:
factorial(51) = factorial(50) * 51
Но наш Функция Выполняет расчеты с нуля каждый раз, когда он называется:
factorial(51) = 51 * 50 * 49 * ... * 2 * 1
Разве это не будет круто, если каким-то образом наше факториал Функция может вспомнить значения из своих предыдущих расчетов и использовать их для ускорения выполнения?
В приезде воспоминание , путь для нашего Функция помнить (кэш) результаты. Теперь, когда вы базовое понимание того, что мы пытаемся достичь, вот формальное определение:
Memoingize В простые термины означает запоминание или хранить в памяти. Немередная функция обычно быстрее, потому что, если функция вызывается впоследствии с предыдущим значением (ыми), то вместо выполнения функции мы получили бы результат из кэша.
Вот что может выглядеть простая воменая функция (И вот кодепен Если вы хотите взаимодействовать с ним) :
// a simple function to add something
const add = (n) => (n + 10);
add(9);
// a simple memoized function to add something
const memoizedAdd = () => {
let cache = {};
return (n) => {
if (n in cache) {
console.log('Fetching from cache');
return cache[n];
}
else {
console.log('Calculating result');
let result = n + 10;
cache[n] = result;
return result;
}
}
}
// returned function from memoizedAdd
const newAdd = memoizedAdd();
console.log(newAdd(9)); // calculated
console.log(newAdd(9)); // cachedНамещение воспоминания
Некоторые вынос из вышеуказанного кода:
MemoiedaddВозвращаетФункциякоторый вызывается позже. Это возможно, потому что в JavaScript функции – это объекты первого класса, которые позволяют нам использовать их как Функции высшего порядка и вернуть другую функцию.кэшможно вспомнить его Значения Так как возвращенная функция имеет закрытие над ним.- Важно, чтобы мемуизорованная функция – чистый Отказ Чистая функция вернет один и тот же вывод для конкретного ввода, независимо от того, сколько раз его называют, что делает
кэшработать, как ожидалось.
Написание собственной функции воменения
Предыдущий код работает нормально, но что, если мы хотели превратить любую функцию в памятную функцию?
Вот как написать собственную функцию воменения ( Codepen ):
// a simple pure function to get a value adding 10
const add = (n) => (n + 10);
console.log('Simple call', add(3));
// a simple memoize function that takes in a function
// and returns a memoized function
const memoize = (fn) => {
let cache = {};
return (...args) => {
let n = args[0]; // just taking one argument here
if (n in cache) {
console.log('Fetching from cache');
return cache[n];
}
else {
console.log('Calculating result');
let result = fn(n);
cache[n] = result;
return result;
}
}
}
// creating a memoized function for the 'add' pure function
const memoizedAdd = memoize(add);
console.log(memoizedAdd(3)); // calculated
console.log(memoizedAdd(3)); // cached
console.log(memoizedAdd(4)); // calculated
console.log(memoizedAdd(4)); // cachedТеперь это здорово! Это просто Memoize Функция обернет любой простой Функция в воменутый эквивалент. Код отлично работает для простых функций, и его можно легко настроить для обработки любого количества аргументы согласно вашим потребностям. Другая альтернатива – воспользоваться некоторыми библиотеками де-факто, таких как:
- Лоташ ‘s
_.Мемиазображение (ФУНК, [Resolver]) - ES7
@memoizeдекораторы от дезон
Немередние рекурсивные функции
Если вы попробуете проходить в рекурсивной функции для Memoize функция выше или _.Мемиазображение От Lodash результаты не будут, как ожидаются, поскольку рекурсивная функция на его последующих вызовах завершится вызова себе вместо метеозной функции, тем самым не использующую кэш Отказ
Просто убедитесь, что ваша рекурсивная функция вызывает памятную функцию. Вот как вы можете настроить учебник факториал Пример ( Кодепен ):
// same memoize function from before
const memoize = (fn) => {
let cache = {};
return (...args) => {
let n = args[0];
if (n in cache) {
console.log('Fetching from cache', n);
return cache[n];
}
else {
console.log('Calculating result', n);
let result = fn(n);
cache[n] = result;
return result;
}
}
}
const factorial = memoize(
(x) => {
if (x === 0) {
return 1;
}
else {
return x * factorial(x - 1);
}
}
);
console.log(factorial(5)); // calculated
console.log(factorial(6)); // calculated for 6 and cached for 5Несколько пунктов для заметок из этого кода:
-
факториалФункция рекурсивно вызывает воспоминание о себе. - Вометочная функция кэширует значения предыдущих факториалов, которые значительно улучшают расчеты, поскольку они могут быть повторно использованы
факториал (6) * факториал (5)
Мемонография такая же, как кэширование?
Да, вид. Memoation на самом деле является определенным типом кэширования. В то время как кэширование может означать в общем в любой методике хранения (например, HTTP Cacaching ) Для будущего использования Memoingiance специально включает кэширование Обратные значения a Функция Отказ
Когда восполнить ваши функции
Хотя это может выглядеть как память может использоваться со всеми функциями На самом деле он имеет ограниченные случаи использования:
- Для того, чтобы воспокоить функцию, она должна быть чистой, так что возвратные значения одинаковы для того же ввода каждый раз
- Memoingize – это компромисс между добавленной пространством и дополнительной скоростью и, таким образом, только значимым для функций, имеющих ограниченное входное диапазон, так что кэшированные значения могут быть использованы чаще
- Это может показаться, что вы должны восполнить ваши вызовы API, однако это не нужно, потому что браузер автоматически кэширует их для вас. См. HTTP Caching Для получения более подробной информации
- Лучший случай для использования, который я нашел для мемонациональных функций Для тяжелых вычислительных функций которые могут значительно улучшить производительность (факториал и фибоначчи не очень хорошие реальные примеры мира)
- Если вы в React/Redux, вы можете проверить повторно повторно который использует Memoied Selector Чтобы вычисления проходили только расчеты, когда изменение происходит в соответствующей части дерева состояния.
дальнейшее чтение
Следующие ссылки могут быть полезны, если вы хотите больше узнать о некоторых темах из этой статьи более подробно:
- Функции высшего порядка в JavaScript
- Закрытие в JavaScript
- Чистые функции
- Лодаш
_.Мемиазображениедокументы и исходный код - Дополнительные примеры памяти здесь и здесь
- REVENTJS/RESELECT.
Я надеюсь, что эта статья была полезна для вас, и вы получили лучшее понимание воспоминания в JavaScript:)
Вы можете следовать за мной на Twitter Для последних обновлений. Я также начал публиковать более свежие сообщения на моем личном Блог Отказ
Оригинал: “https://www.freecodecamp.org/news/understanding-memoize-in-javascript-51d07d19430e/”