javascript记忆特性
2009-11-03 00:30 BlueDream 阅读(601) 评论(0) 编辑 收藏 举报函数可以通过对象来存储先前操作的结果,从而减少无谓的运算,这种优化被称为记忆.
比如说:用JS来递归实现斐波那契数列.Fibonacci一个运算数是前两个运算数的和.最前面的两个数字是0和1.
最容易想到的递归方式就是:
var fibonacci = function(n){
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
这里可以看到 比如计算10的斐波那契数.要把9以前每次斐波那契都重新算一遍.显然损失了很多效率.这里我们就可以用
一个数组把每次计算的值给"记忆"起来.以便下次调用可以直接取出.
还有阶乘函数的递归实现:
var factorial = function(n){
return n == 1 ? n : n * arguments.callee(n - 1);
}
return n == 1 ? n : n * arguments.callee(n - 1);
}
最后为了我们提供了一个记忆模板.可以自己定制规则去实现记忆功能而优化不必要的计算.
记忆模板:
var memoizer = function(memo/*记忆数组*/, func/*自定义递归函数*/){
// 提供一个闭包方法
var shell = function(n/*递归次数*/){
var r = memo[n];
if(typeof r !== 'number'){ // 如果存储中没有
r = func(shell, n); // 递归调用自定义函数
memo[n] = r; // 将没有存储的值存储进去
}
return r;
};
return shell;
};
// 提供一个闭包方法
var shell = function(n/*递归次数*/){
var r = memo[n];
if(typeof r !== 'number'){ // 如果存储中没有
r = func(shell, n); // 递归调用自定义函数
memo[n] = r; // 将没有存储的值存储进去
}
return r;
};
return shell;
};
最后给出测试代码,以及使用形式:
<script type="text/javascript">
<!--
var memoizer = function(memo/*记忆数组*/, func/*自定义递归函数*/){
// 提供一个闭包方法
var shell = function(n/*递归次数*/){
var r = memo[n];
if(typeof r !== 'number'){ // 如果存储中没有
r = func(shell, n); // 递归调用自定义函数
memo[n] = r; // 将没有存储的值存储进去
}
return r;
};
return shell;
};
// 原形式
var fibonacci = function(n){
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
// 记忆形式
var fibonacci2 = memoizer([0, 1]/*初始化记忆仓库*/, /*提供自定义递归公式*/function(shell, n){
return shell(n - 1) + shell(n - 2);
});
// ===========================
//
// fibonacci形式比较
//
// ===========================
for(var i = 0; i < 10; i++){
document.write(fibonacci(i) + ' ');
}
document.write('==');
for(var j = 0; j < 10; j++){
document.write(fibonacci2(j) + ' ');
}
// 原形式
var factorial = function(n){
return n == 1 ? n : n * arguments.callee(n - 1);
}
// 记忆形式
var factorial2 = memoizer([1, 1]/*初始化记忆仓库*/, /*提供自定义递归公式*/function(shell, n){
return n * shell(n - 1);
});
// ===========================
//
// factorial形式比较
//
// ===========================
document.write('<br/>');
document.write(factorial(5) + ' == ');
document.write(factorial2(5));
//-->
</script>
<!--
var memoizer = function(memo/*记忆数组*/, func/*自定义递归函数*/){
// 提供一个闭包方法
var shell = function(n/*递归次数*/){
var r = memo[n];
if(typeof r !== 'number'){ // 如果存储中没有
r = func(shell, n); // 递归调用自定义函数
memo[n] = r; // 将没有存储的值存储进去
}
return r;
};
return shell;
};
// 原形式
var fibonacci = function(n){
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
// 记忆形式
var fibonacci2 = memoizer([0, 1]/*初始化记忆仓库*/, /*提供自定义递归公式*/function(shell, n){
return shell(n - 1) + shell(n - 2);
});
// ===========================
//
// fibonacci形式比较
//
// ===========================
for(var i = 0; i < 10; i++){
document.write(fibonacci(i) + ' ');
}
document.write('==');
for(var j = 0; j < 10; j++){
document.write(fibonacci2(j) + ' ');
}
// 原形式
var factorial = function(n){
return n == 1 ? n : n * arguments.callee(n - 1);
}
// 记忆形式
var factorial2 = memoizer([1, 1]/*初始化记忆仓库*/, /*提供自定义递归公式*/function(shell, n){
return n * shell(n - 1);
});
// ===========================
//
// factorial形式比较
//
// ===========================
document.write('<br/>');
document.write(factorial(5) + ' == ');
document.write(factorial2(5));
//-->
</script>
结果是正确的,但效率高了许多.
0 1 1 2 3 5 8 13 21 34 ==0 1 1 2 3 5 8 13 21 34
120 == 120
120 == 120