diff --git a/packages/function-memoize/index.js b/packages/function-memoize/index.js index 65b565939..0439851c3 100644 --- a/packages/function-memoize/index.js +++ b/packages/function-memoize/index.js @@ -23,7 +23,40 @@ module.exports = memoize; sum(10, 20) -- Cache hit! */ -function memoize(callback, resolver) { +function Order() { + this.keys = []; + this.cache = {}; +} + +Order.prototype = { + 'has': function(key) { + return this.cache.hasOwnProperty(key); + }, + + 'get': function(key) { + return this.cache[key]; + }, + + 'set': function(key, value) { + if (!this.has(key)) { + this.keys.push(key); + } + + this.cache[key] = value; + }, + + 'delete': function(key) { + var index = this.keys.indexOf(key); + this.keys.splice(index, 1); + delete this.cache[key]; + }, + + 'keys': function() { + return this.keys; + }, +}; + +function memoize(callback, resolver, options) { if (typeof callback !== 'function') { throw new Error('`callback` should be a function'); } @@ -32,17 +65,26 @@ function memoize(callback, resolver) { throw new Error('`resolver` should be a function'); } - var cache = {}; + if (options !== undefined && typeof options !== 'object') { + throw new Error('`options` should be an object'); + } + + var cache = 'Map' in (typeof window === 'undefined' ? global : window) ? new Map() : new Order(); var memoized = function() { var args = Array.prototype.slice.call(arguments); // to simplify JSON.stringify var key = resolver ? resolver.apply(this, args) : JSON.stringify(args); - if (!(key in cache)) { - cache[key] = callback.apply(this, args); + if (!cache.has(key)) { + cache.set(key, callback.apply(this, args)); + } + + if (typeof options.max === 'number' && cache.size > options.max) { + var firstKey = cache.keys()[0]; + cache.delete(firstKey); } - return cache[key]; + return cache.get(key); }; memoized.cache = cache;