JavaScriptMemoization allows functions to also have memory functions _ javascript skills

Source: Internet
Author: User
Functions can use objects to remember the results of previous operations, so as to avoid unnecessary operations. Such optimization is called memory ). It is very convenient to optimize JavaScript objects and arrays. For example, we want a recursive function to calculate the Fibonacci series. A Fibonacci number is the sum of the first two. The first two digits are 0 and 1.

The Code is as follows:


Var maid = function (n ){
Return n <2? N: Maid (n-1) + maid (n-2 );
};

For (var I = 0; I <= 10; I + = 1 ){
Document. writeln ('//' + I + ':' + fig (I ));
}

// 0: 0
// 1: 1
// 2: 1
// 3: 2
// 4: 3
// 5: 5
// 6: 8
// 7: 13
// 8: 21
// 9: 34
// 10: 55


This can work, but it does a lot of unnecessary work. The Fibonacci function is called 453 times. We called it 11 times, and it called it 442 times to calculate the value that may have just been computed. If we enable this function to have a memory function, we can significantly reduce its computing workload.

We store our stored results in an array named memo, and the stored results can be hidden in the closure. When our function is called, the function first checks whether the calculation result is known. If the result is known, the stored result is returned immediately.

The Code is as follows:


Var maid = function (){
Var memo = [0, 1];
Var fib = function (n ){
Var result = memo [n];
If (typeof result! = 'Number '){
Result = fib (n-1) + fib (n-2 );
Memo [n] = result;
}
Return result;
};
Return fib;
}();


This function returns the same result, but it is only called 29 times. We called it 11 times and it called it 18 times to get the previously stored results.
The above content from: http://demon.tw/programming/javascript-memoization.html

Realazy provides a JavaScript Memoization implementation on the blog. Memoization is the cache of function return values. For example, if a function parameter corresponds to a hash list of return results one by one, the wiki actually provides a detailed explanation, I will not elaborate on it. I will only discuss the specific implementation issues. The code in realazy has some problems, such as directly using the string concatenated by parameters as the key to query cache results, if the parameters include objects or arrays, it is difficult to guarantee the unique key. The parameters mentioned in the comment on the first floor cannot be distinguished.
To rewrite it, we should first use a hash table to store cached data:

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];
};
}


Well, the difference is that arrays are directly used as keys, but note that the arguments in the function is a special object implemented by the js interpreter and is not a real array, so we need to convert it ......
Ps: the original parameters include the method name and Context Reference: fib. fib_memo = Memoize ('fib _ memo ', fib), but in fact, the upper-layer objects can be directly referenced using this function generated by currying. For more complex examples, see John Resig's makeClass, so I changed to directly passing the function reference: fib. fib_memo = Memoize (fib. fib_memo)
The write seems very reliable. Isn't the array composed of parameters unique. But in fact, the array can be used as the property name of the js object because it is processed as a string. That is to say, if the parameter you pass to the function is as follows: (1, 2, 3 ), the cache object will look like this: {"1, 2, 3": somedata}. If your parameter contains an object, such as :( 1, 2, {I: "yy "}), the actual key value will be: "1, 2, [object Object]", so there is no difference between this and the method of concatenating arrays into strings ......
Example:

The Code is as follows:


Var a = [1, 2, {yy: '0'}];
Var B = [1, 2, {xx: '1'}];
Var obj = {};
Obj [a] = "111 ";
Obj [B] = "222 ";
For (var I in obj)
Alert (I + "=" + obj [I]); // only "222, [object Object] = ", obj [a] = "111" is overwritten


It is unreliable to directly use parameters as key names ............ Try another method:

The Code is as follows:


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];
};
}


The preceding problem can be completely avoided. Instead of using the hash key-Value Pair index, the function parameters and results are cached in two lists respectively, and the entire parameter list is traversed for comparison each time, find the corresponding key name/ID and then retrieve data from the result list. The equal Method for comparing arrays is as follows:

The Code is as follows:


Function equal (first, second ){
If (! First |! Second | first. constructor! = Second. constructor)
Return false;
If (first. length & typeof first! = "String ")
For (var I = 0, l = (first. length> second. length )? First. length: second. length; I If (! Equal (first [I], second [I]) return false;
}
Else if (typeof first = 'object ')
For (var n in first ){
If (! Equal (first [n], second [n]) return false;
}
Else
Return (first = second );
Return true;
}


Do not directly use = to compare arrays in arguments and args, so that the memory reference is compared, rather than the parameter content.
The speed of this method is very slow, but the equal method does not affect much. However, when the number of cached results is large, it is inefficient to traverse the parameter list every time (for a series of more than 80 fibonacci, both firefox3 and safari3 require about 40 ms)
If there are not many parameter changes or parameters are not accepted in actual applications, you can refer to One-Line JavaScript Memoization by Oliver Steel to solve the problem in a very short functional style:

The Code is as follows:


Function Memoize (o, p ){
Var f = o [p], mf, value;
Var s = function (v) {return o [p] = v | mf };
(Mf = function (){
(S (function () {return value}). reset = mf. reset;
Return value = f. apply (this, arguments); // The parameter has been modified and can be accepted.
}). Reset = s )();
}


Example:

The Code is as follows:


Var fib = {
Temp: function (n ){
For (var I = 0; I <10000; I ++)
N = n + 2;
Return n;
}
}
Memoize (fib, "temp"); // Let fib. temp cache the returned value
Fib. temp (16); // execution result: 20006, cached
Fib. temp (20); // result: 20006
Fib. temp (10); // result: 20006
Fib. temp. reset (); // reset the cache
Fib. temp (10); // result: 20010

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.