15 记忆
有时候可以把先前计算过的结果记录在某个对象中,避免重复计算。
假设我们想通过递归来计算 Fibonacci 数列。一个 Fibonacci 数字是之前的两个 Fibonacci 数字之和,最前面的两个数字是 0 和 1:
var fiboncci = 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; }(); for (var i = 0; i <= 10; i += 1) { console.log(i + ": " + fiboncci(i)); }
我们把计算结果存储在 memo 数组中,它被隐藏在闭包里。函数被调用时,它会先检查计算结果是否已存在,如果存在就立即返回。
我们对这个例子进行扩展,构造一个带记忆功能的函数:
/** * 带记忆功能的函数 * @param memo 初始的 memo 数组 * @param formula 公式函数 * @returns {Function} */ var memoizer = function (memo, formula) { var recur = function (n) { var result = memo[n]; if (typeof result != 'number') { result = formula(recur, n); memo[n] = result; } return result; }; return recur; };
这个函数会返回一个可以管理 meno 存储参数和在需要时调用 formula 函数的 recur 函数。recur 函数和它的参数会被传递给 formula 函数(就是公式)。是不是感觉有点绕,我们来看看实例就会清楚啦。
现在我们使用 memoizer 函数来重新定义 fibonacci 函数:
/** * 斐波那契 * @type {Function} */ var fibonacci = memoizer([0, 1], function (recur, n) { return recur(n - 1) + recur(n - 2); }); console.log(fibonacci(10));//55
这样清楚了吧,使用这个函数可以极大地减少我们的工作量哦,比如下面的这个阶乘函数:
/** * 阶乘 * @type {Function} */ var factorial = memoizer([1, 1], function (recur, n) { return n * recur(n - 1); }); console.log(factorial(10));//3628800
感兴趣的朋友还可以使用本站在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行结果。
更多关于JavaScript相关内容可查看本站专题:《JavaScript常用函数技巧汇总》、《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。