Complete memoization/caching solution for JavaScript functions with support for any argument types, async/promise functions, cache expiration, and advanced cache management features
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core memoization functionality that wraps functions to cache their results based on input arguments. Supports configurable argument handling, custom cache key generation, and multiple caching strategies for optimal performance across different use cases.
Creates a memoized version of any function with automatic result caching.
/**
* Create a memoized version of a function
* @param {Function} fn - Function to memoize (required)
* @param {Object} options - Configuration options (optional)
* @returns {Function} Memoized function with additional cache methods
*/
function memoize(fn, options);Usage Examples:
const memoize = require("memoizee");
// Simple function memoization
function fibonacci(n) {
if (n < 2) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
const memoizedFib = memoize(fibonacci);
memoizedFib(40); // Computed once, then cached
// Function with multiple arguments
function multiply(a, b, c) {
return a * b * c;
}
const memoizedMultiply = memoize(multiply);
memoizedMultiply(2, 3, 4); // 24 (computed)
memoizedMultiply(2, 3, 4); // 24 (from cache)Control how many arguments are considered for cache key generation.
/**
* Configure argument length handling
* @param {number|false} length - Number of arguments to consider, or false for dynamic
*/
const options = {
length: number | false
};Usage Examples:
// Fixed argument length (ignores extra arguments)
const memoized = memoize(fn, { length: 2 });
memoized("foo", 3, "ignored"); // Third argument ignored
memoized("foo", 3, "different"); // Cache hit
// Dynamic argument length (considers all arguments)
const dynamicMemoized = memoize(fn, { length: false });
dynamicMemoized("foo"); // Different cache entry
dynamicMemoized("foo", "bar"); // Different cache entryOptimized caching for functions with arguments that convert to unique strings.
/**
* Enable primitive mode for string-convertible arguments
* @param {boolean} primitive - Use primitive mode optimization
*/
const options = {
primitive: boolean
};Usage Examples:
// Primitive mode for high-performance caching
const memoized = memoize(function(path) {
return fs.readFileSync(path, 'utf8');
}, { primitive: true });
memoized("/path/to/file.txt"); // String argument, fast hash lookup
memoized("/path/to/file.txt"); // Cache hit with O(1) accessDefine custom cache key generation logic for complex argument patterns.
/**
* Custom cache key normalization function
* @param {Function} normalizer - Function that generates cache keys from arguments
*/
const options = {
normalizer: function(args) {
// Return string key based on arguments object
return string;
}
};Usage Examples:
// Normalize object arguments by content
const memoized = memoize(function(config) {
return processConfig(config);
}, {
normalizer: function(args) {
return JSON.stringify(args[0]);
}
});
memoized({ api: "v1", timeout: 5000 });
memoized({ timeout: 5000, api: "v1" }); // Different order, same cache key
// Deep object normalization with sorted keys
const deepNormalizer = memoize(expensiveFunction, {
normalizer: function(args) {
const sortedEntries = (obj) =>
Object.entries(obj)
.map(([key, value]) => [
key,
value && typeof value === "object" ? sortedEntries(value) : value
])
.sort();
return JSON.stringify(sortedEntries(args[0]));
}
});Pre-process function arguments before cache key generation and function execution.
/**
* Argument resolver functions for type coercion
* @param {Function[]} resolvers - Array of functions to transform arguments
*/
const options = {
resolvers: [Function, ...]
};Usage Examples:
// Type coercion for consistent caching
const memoized = memoize(function(str, bool) {
return str.repeat(bool ? 2 : 1);
}, {
length: 2,
resolvers: [String, Boolean]
});
memoized(12, 1); // "1212"
memoized("12", true); // Cache hit - resolved to same arguments
memoized({ toString: () => "12" }, {}); // Cache hit - also resolves the same wayOverride existing memoization on already memoized functions.
/**
* Force memoization of already memoized functions
* @param {boolean} force - Override existing memoization
*/
const options = {
force: boolean
};Usage Examples:
const fn = function(x) { return x * 2; };
const memoized1 = memoize(fn, { maxAge: 1000 });
const memoized2 = memoize(memoized1, { maxAge: 5000, force: true });
// Without force: true, memoized1 would be returned unchanged
// With force: true, creates new memoization with different options/**
* Property indicating function is memoized
* @type {boolean}
*/
memoizedFunction.__memoized__ = true;/**
* Delete cached result for specific arguments
* @param {...any} args - Arguments to delete from cache
*/
memoizedFunction.delete(...args);
/**
* Clear all cached results
*/
memoizedFunction.clear();
/**
* Get cached value without triggering function execution
* @param {...any} args - Arguments to lookup
* @returns {any} Cached value or undefined
*/
memoizedFunction._get(...args);
/**
* Check if arguments have a cached result
* @param {...any} args - Arguments to check
* @returns {boolean} True if cached result exists
*/
memoizedFunction._has(...args);Usage Examples:
const memoized = memoize(expensiveFunction);
// Cache management
memoized(1, 2); // Execute and cache
memoized._has(1, 2); // true
memoized._get(1, 2); // Returns cached value
memoized.delete(1, 2); // Remove from cache
memoized._has(1, 2); // false
// Clear entire cache
memoized(1, 2);
memoized(3, 4);
memoized.clear(); // All entries removed// For functions with potentially unlimited inputs
const memoized = memoize(fn, {
max: 1000, // Limit cache size
dispose: (value) => { // Cleanup when entries are evicted
if (value && value.cleanup) value.cleanup();
}
});// More efficient when you know exact argument count
const memoized = memoize(fn, { length: 3 });
// Use false only when argument count varies significantly
const variadic = memoize(fn, { length: false });