mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-11 11:27:50 +00:00
Add _.memoize.Cache to allow using ES6 Map/WeakMap.
This commit is contained in:
committed by
John-David Dalton
parent
12ad5d53c9
commit
f7dc3b9ce4
66
lodash.js
66
lodash.js
@@ -6376,6 +6376,11 @@
|
|||||||
* invoked with the `this` binding of the memoized function. The result cache
|
* invoked with the `this` binding of the memoized function. The result cache
|
||||||
* is exposed as the `cache` property on the memoized function.
|
* is exposed as the `cache` property on the memoized function.
|
||||||
*
|
*
|
||||||
|
* The mechanism by which memoize caches results can be customized by setting
|
||||||
|
* a value for the `_.memoize.Cache` property. The objects created by this
|
||||||
|
* constructor must (partially) implement the `Map` interface with `get`,
|
||||||
|
* `set` and `has` functions.
|
||||||
|
*
|
||||||
* @static
|
* @static
|
||||||
* @memberOf _
|
* @memberOf _
|
||||||
* @category Function
|
* @category Function
|
||||||
@@ -6402,6 +6407,33 @@
|
|||||||
* upperCase.cache.fred = 'BARNEY'
|
* upperCase.cache.fred = 'BARNEY'
|
||||||
* upperCase('fred');
|
* upperCase('fred');
|
||||||
* // => 'BARNEY'
|
* // => 'BARNEY'
|
||||||
|
*
|
||||||
|
* // Using a custom memoize cache
|
||||||
|
* _.memoize.Cache = Map;
|
||||||
|
*
|
||||||
|
* // Using a hand-cranked memoize cache wrapper.
|
||||||
|
* function MyCache() {
|
||||||
|
* this.__wrapper__ = [];
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* _.extend(MyCache.prototype, {
|
||||||
|
* get: function(key) {
|
||||||
|
* return _.find(this.__wrapper__, function(cached) {
|
||||||
|
* return _.identity(key) === cached.key;
|
||||||
|
* }).value;
|
||||||
|
* },
|
||||||
|
* set: function(key, value) {
|
||||||
|
* this.__wrapper__.push({ key: key, value: value });
|
||||||
|
* return this;
|
||||||
|
* },
|
||||||
|
* has: function(key) {
|
||||||
|
* return _.some(this.__wrapper__, function(cached) {
|
||||||
|
* return _.identity(key) === cached;
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* _.memoize.Cache = MyCache;
|
||||||
*/
|
*/
|
||||||
function memoize(func, resolver) {
|
function memoize(func, resolver) {
|
||||||
if (!isFunction(func) || (resolver && !isFunction(resolver))) {
|
if (!isFunction(func) || (resolver && !isFunction(resolver))) {
|
||||||
@@ -6412,15 +6444,16 @@
|
|||||||
if (key == '__proto__') {
|
if (key == '__proto__') {
|
||||||
return func.apply(this, arguments);
|
return func.apply(this, arguments);
|
||||||
}
|
}
|
||||||
var cache = memoized.cache;
|
var cache = memoized.Cache;
|
||||||
return hasOwnProperty.call(cache, key)
|
if (!cache.has(key)) cache.set(key, func.apply(this, arguments));
|
||||||
? cache[key]
|
return cache.get(key);
|
||||||
: (cache[key] = func.apply(this, arguments));
|
|
||||||
};
|
};
|
||||||
memoized.cache = {};
|
memoized.Cache = new memoize.Cache;
|
||||||
return memoized;
|
return memoized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memoize.Cache = Cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a function that negates the result of the predicate `func`. The
|
* Creates a function that negates the result of the predicate `func`. The
|
||||||
* `func` predicate is invoked with the `this` binding and arguments of the
|
* `func` predicate is invoked with the `this` binding and arguments of the
|
||||||
@@ -7673,6 +7706,29 @@
|
|||||||
return isObject(object) ? nativeKeys(object) : [];
|
return isObject(object) ? nativeKeys(object) : [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default internal caching mechanism used by _.memoize which
|
||||||
|
* implements the subset of the Map interface (get, set and
|
||||||
|
* has) required my _.memoize.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function Cache() {
|
||||||
|
this.__wrapped__ = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
assign(Cache.prototype, {
|
||||||
|
get: function(key) {
|
||||||
|
return this.__wrapped__[key];
|
||||||
|
},
|
||||||
|
set: function(key, value) {
|
||||||
|
this.__wrapped__[key] = value;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
has: function(key) {
|
||||||
|
return hasOwnProperty.call(this.__wrapped__, key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an array of the own and inherited enumerable property names of `object`.
|
* Creates an array of the own and inherited enumerable property names of `object`.
|
||||||
*
|
*
|
||||||
|
|||||||
47
test/test.js
47
test/test.js
@@ -7506,16 +7506,14 @@
|
|||||||
deepEqual(actual, shadowedProps);
|
deepEqual(actual, shadowedProps);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should expose a `cache` object on the `memoized` function', 4, function() {
|
test('should expose a `cache` object on the `memoized` function which implements `Map` interface', 2, function() {
|
||||||
_.times(2, function(index) {
|
_.times(2, function(index) {
|
||||||
var resolver = index && _.identity,
|
var resolver = index && _.identity,
|
||||||
memoized = _.memoize(_.identity, resolver);
|
memoized = _.memoize(_.identity, resolver);
|
||||||
|
|
||||||
memoized('a');
|
memoized('a');
|
||||||
strictEqual(memoized.cache.a, 'a');
|
|
||||||
|
|
||||||
memoized.cache.a = 'b';
|
deepEqual(_.methods(memoized.Cache), ['get', 'set', 'has']);
|
||||||
strictEqual(memoized('a'), 'b');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -7533,7 +7531,46 @@
|
|||||||
memoized('__proto__');
|
memoized('__proto__');
|
||||||
|
|
||||||
strictEqual(count, 2);
|
strictEqual(count, 2);
|
||||||
ok(!(memoized.cache instanceof Array));
|
ok(!(memoized.Cache instanceof Array));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should allow cache to be set to custom implementation of Map interface', 4, function() {
|
||||||
|
_.times(2, function() {
|
||||||
|
var firstObject = { id: 'a1' },
|
||||||
|
secondObject = { id: 'a2' };
|
||||||
|
|
||||||
|
function MyCache() {
|
||||||
|
this.__wrapped__ = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
_.extend(MyCache.prototype, {
|
||||||
|
get: function(key) {
|
||||||
|
return _.find(this.__wrapped__, function(cached) {
|
||||||
|
return _.identity(key) === cached.key;
|
||||||
|
}).value;
|
||||||
|
},
|
||||||
|
set: function(key, value) {
|
||||||
|
this.__wrapped__.push({ key: key, value: value });
|
||||||
|
},
|
||||||
|
has: function(key) {
|
||||||
|
return _.some(this.__wrapped__, function(cached) {
|
||||||
|
return _.identity(key) === cached.key;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_.memoize.Cache = MyCache;
|
||||||
|
|
||||||
|
var memoized = _.memoize(function(val) {
|
||||||
|
return 'id is ' + val.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
var firstResult = memoized(firstObject);
|
||||||
|
var secondResult = memoized(secondObject);
|
||||||
|
|
||||||
|
strictEqual(firstResult, 'id is ' + firstObject.id);
|
||||||
|
strictEqual(secondResult, 'id is ' + secondObject.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}());
|
}());
|
||||||
|
|||||||
Reference in New Issue
Block a user