The following is from John Hann's implementation. This code caught my attention. It uses a clever method to cache the results of method calls.
Code analysis:
// memoize: A general method for caching using memoization
// func: method to be cached
// context: method execution context
// Note: The method must be externally accessible and the parameters must be character serializable
function memoize (func, context) {
Function memoizeArg (argPos) { //Parameter indicates the position of the parameter in the original method
var cache = {}; //The key of this cache is the parameter, and the value is the execution result
return function () { //Return a function closure
If (argPos == 0) { //The first parameter, if the parameter does not exist in the cached key, execute the original function and store the execution result
If (!(arguments[argPos] in cache)) {
cache[arguments[argPos]] = func.apply(context, arguments);
return cache[arguments[argPos]];
Else {// is not the first parameter. If the parameter does not exist in the cache key, it is recursively executing the Memoizearg method. The position of the parameter in the original method-1
If (!(arguments[argPos] in cache)) {
cache[arguments[argPos]] = memoizeArg(argPos - 1);
return cache[arguments[argPos]].apply(this, arguments);
}
}
var arity = func.arity || func.length; //The length of the func parameter, the length attribute is used in JavaScript, and the arity attribute is used for others
Return memoizeArg(arity - 1); //Recurse from the last parameter
}
Use:
Copy code
alert(mem.call(this,2,1,2));
alert(mem.call(this,3,1,3));
alert(mem.call(this,2,2,4));
It seems simple, but it may not be easy to understand at first glance. However, if you are familiar with the use of closures, it will be easy to understand. After the above several calls to mem.call, a tree is formed, each node is a closure, each closure has a cache, and the key of each cache is a tree branch:
(Note: The "result" in the above picture is also a closure, but argPos is 0)
But there are many ways, for example, limbboy said:
Copy code
The code is as follows:
function Memoize(fn){
var cache = {};
Return function(){
var key = [];
for( var i=0, l = arguments.length; i < l; i )
key.push(arguments[i]);
If( !(key in cache) )
cache[key] = fn.apply(this, arguments);
return cache[key];
};
}
The implementation is simpler, but push the parameters into an array, and then use the array as the key, and the key only supports string type, so you need to pay attention to this when using it (for example, an object may only be seen after tostring "[object Object]"), its function is weaker than the one above.
It is not difficult to improve this. Just create a separate object for the parameter, and the original cache object and this separate parameter object are associated with an ID:
function Memoize(fn){
var cache = {}, args = {};
Return function(){
for( var i=0, key = args.length; i < key; i ) {
If( equal( args[i], arguments ) )
return cache[i];
}
args[key] = arguments;
cache[key] = fn.apply(this, arguments);
return cache[key];
};
}
There are other methods, which can be written as concise functional methods.