Fastest memoization library that supports N arguments with customizable caching and serialization
npx @tessl/cli install tessl/npm-fast-memoize@2.5.0Fast Memoize is a high-performance memoization library for JavaScript that caches function results to optimize expensive computations. It supports N arguments with automatic strategy selection, customizable caching mechanisms, and serializers, designed for maximum speed through optimized algorithms and zero runtime dependencies.
npm install fast-memoizeFor ES6 modules:
import memoize from 'fast-memoize';For CommonJS:
const memoize = require('fast-memoize');const memoize = require('fast-memoize');
// Basic memoization
const expensiveFunction = (a, b, c) => {
// Some expensive computation
return a + b + c;
};
const memoizedFunction = memoize(expensiveFunction);
// First call - executes the function
const result1 = memoizedFunction(1, 2, 3); // 6
// Second call - returns cached result
const result2 = memoizedFunction(1, 2, 3); // 6 (from cache)Fast Memoize uses automatic strategy selection based on function arity:
function.lengthCreates a memoized version of any function with automatic optimization strategy selection.
/**
* Creates a memoized version of the provided function
* @param fn - The function to memoize
* @param options - Configuration options
* @returns Memoized version of the input function
*/
function memoize<F extends (...args: any[]) => any>(
fn: F,
options?: Options<F>
): F;
interface Options<F extends (...args: any[]) => any> {
cache?: Cache<string, ReturnType<F>>;
serializer?: Serializer;
strategy?: MemoizeFunc;
}Usage Examples:
// Basic memoization with automatic strategy
const memoizedAdd = memoize((a, b) => a + b);
// With custom cache
const memoizedWithCache = memoize(expensiveFunction, {
cache: {
create() {
const store = new Map();
return {
has(key) { return store.has(key); },
get(key) { return store.get(key); },
set(key, value) { store.set(key, value); }
};
}
}
});
// With custom serializer
const memoizedWithSerializer = memoize(complexFunction, {
serializer: (args) => JSON.stringify(args)
});Explicit strategy functions for optimal performance control.
Optimized strategy for functions with multiple arguments or rest parameters.
/**
* Variadic memoization strategy for multiple-argument functions
* @param fn - The function to memoize
* @param options - Configuration options
* @returns Memoized function using variadic strategy
*/
memoize.strategies.variadic<F extends (...args: any[]) => any>(
fn: F,
options?: Options<F>
): F;Usage:
// For functions with rest parameters
function multiply(multiplier, ...args) {
return args.map(element => multiplier * element);
}
const memoizedMultiply = memoize(multiply, {
strategy: memoize.strategies.variadic
});Optimized strategy for single-argument functions.
/**
* Monadic memoization strategy for single-argument functions
* @param fn - The function to memoize
* @param options - Configuration options
* @returns Memoized function using monadic strategy
*/
memoize.strategies.monadic<F extends (...args: any[]) => any>(
fn: F,
options?: Options<F>
): F;Usage:
// Explicitly use monadic strategy
const memoizedSingleArg = memoize(singleArgFunction, {
strategy: memoize.strategies.monadic
});Define custom caching mechanisms for specialized use cases.
interface Cache<K, V> {
/**
* Cache factory that creates cache instances
* @returns Cache instance with get, set, and has methods
*/
create(): CacheInstance<K, V>;
}
interface CacheInstance<K, V> {
has(key: K): boolean;
get(key: K): V;
set(key: K, value: V): void;
}Usage:
// Custom LRU cache example
const customCache = {
create() {
const cache = new Map();
const maxSize = 100;
return {
has(key) { return cache.has(key); },
get(key) { return cache.get(key); },
set(key, value) {
if (cache.size >= maxSize) {
const firstKey = cache.keys().next().value;
cache.delete(firstKey);
}
cache.set(key, value);
}
};
}
};
const memoizedWithLRU = memoize(expensiveFunction, {
cache: customCache
});Define how function arguments are serialized for cache keys.
/**
* Custom serializer function for argument serialization
* @param args - Function arguments to serialize
* @returns String representation for cache key
*/
type Serializer = (args: any[]) => string;Usage:
// Custom serializer for functions with function arguments
const customSerializer = (args) => {
return Array.from(args).map(arg => {
if (typeof arg === 'function') {
return arg.toString();
}
return JSON.stringify(arg);
}).join('|');
};
const memoizedWithCustomSerializer = memoize(functionWithCallbacks, {
serializer: customSerializer
});type Func = (...args: any[]) => any;
interface Cache<K, V> {
create: CacheCreateFunc<K, V>;
}
interface CacheCreateFunc<K, V> {
(): CacheInstance<K, V>;
}
interface CacheInstance<K, V> {
get(key: K): V;
set(key: K, value: V): void;
has(key: K): boolean;
}
type Serializer = (args: any[]) => string;
interface Options<F extends Func> {
cache?: Cache<string, ReturnType<F>>;
serializer?: Serializer;
strategy?: MemoizeFunc;
}
interface MemoizeFunc {
<F extends Func>(fn: F, options?: Options<F>): F;
}
interface Memoize extends MemoizeFunc {
strategies: {
variadic: MemoizeFunc;
monadic: MemoizeFunc;
};
}let fibonacci = n => n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
fibonacci = memoize(fibonacci);
console.log(fibonacci(40)); // Fast execution due to memoizationconst fetchUserData = memoize(async (userId) => {
const response = await fetch(`/api/users/${userId}`);
return response.json();
});
// Subsequent calls with same userId return cached data
const userData = await fetchUserData(123);function processData(options, ...data) {
return data.map(item => ({ ...item, ...options }));
}
// Must use variadic strategy for rest parameters
const memoizedProcessData = memoize(processData, {
strategy: memoize.strategies.variadic
});Fast Memoize does not throw exceptions during normal operation. However, the following scenarios should be considered:
get, set, or has methods, they will be propagatedJSON.stringify)